Di cosa parlo in questo tutorial:
In questo nuovo video della serie/corso di Supabase in Italiano, parleremo di RLS e di come grazie ad esse è possibile costruire un'applicazione che sia effettivamente sicura. Nel video ribadiamo concetti come le operazioni CRUD (Creazione, Lettura, Modifica ed Eliminazione dei dati) e ne affrontiamo di nuovi come: le Policy di sicurezza RLS, nonchè il concetto di Server web locale e di origine.
Codice di implementazione
Copia e incolla questo codice nel tuo editor preferito e inserisci le tue credenziali pubbliche per la connessione a Supabase. Ricorda di aggiungere le tabelle e le policy di sicurezza RLS come nel video per evitare errori, come colonne non trovate o di tipo dato sbagliato:
Puoi scaricare il codice in una cartella .zip direttamente da qui: Download del codice sorgente tramite file ZIP.
Oppure incollare a mano il codice:
01-rls-policies-examples.sql
-- Abilitazione di RLS sulla tabella desiderata
ALTER TABLE products ENABLE ROW LEVEL SECURITY;
-- 1. Permetti la lettura (SELECT) a CHIUNQUE (anonimi e autenticati)
CREATE POLICY "Nome della regola di sicurezza"
ON products
FOR SELECT
USING (true);
-- 2. Permetti l'inserimento (INSERT) SOLO agli utenti autenticati
CREATE POLICY "Solo utenti autenticati possono creare nuove righe nella tabella desiderata"
ON products
FOR INSERT
TO authenticated
WITH CHECK (true);
supabase_crud_no_css.html
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Supabase CRUD Operations</title>
<!-- Libreria Supabase JS via CDN -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
</head>
<body>
<h1>Supabase CRUD Example</h1>
<!-- Operazione CREATE (Insert) -->
<section>
<h2>2. Create (Insert)</h2>
<form id="createForm" onsubmit="createRecord(event)">
<label for="createTitle">Titolo / Nome:</label>
<input type="text" id="createTitle" required><br><br>
<label for="createDesc">Descrizione:</label>
<input type="text" id="createDesc"><br><br>
<button type="submit">Inserisci Record</button>
</form>
</section>
<hr>
<!-- Operazione READ (Select) -->
<section>
<h2>3. Read (Select)</h2>
<button onclick="readRecords()">Carica / Ricarica Tutti i Record</button>
<h3>Risultati:</h3>
<pre id="outputRead">Nessun dato caricato</pre>
</section>
<hr>
<!-- Operazione UPDATE -->
<section>
<h2>4. Update</h2>
<form id="updateForm" onsubmit="updateRecord(event)">
<label for="updateId">ID Record da aggiornare:</label>
<input type="text" id="updateId" required><br><br>
<label for="updateTitle">Nuovo Titolo:</label>
<input type="text" id="updateTitle" required><br><br>
<label for="updateDesc">Nuova Descrizione:</label>
<input type="text" id="updateDesc"><br><br>
<button type="submit">Aggiorna Record</button>
</form>
</section>
<hr>
<!-- Operazione DELETE -->
<section>
<h2>5. Delete</h2>
<form id="deleteForm" onsubmit="deleteRecord(event)">
<label for="deleteId">ID Record da eliminare:</label>
<input type="text" id="deleteId" required><br><br>
<button type="submit">Elimina Record</button>
</form>
</section>
<script>
let supabaseClient = null;
// 1. Inizializzazione Client
function initSupabase() {
// INSERISCI QUI I TUOI DATI PRESI DALLA DASHBOARD SUPABASE
const SUPABASE_URL = 'IL_TUO_SUPABASE_URL';
const SUPABASE_KEY = 'LA_TUA_SUPABASE_PUBLIC_KEY';
if (!SUPABASE_URL || !SUPABASE_KEY || SUPABASE_URL.includes('TUO-PROGETTO')) {
console.log('Inserisci sia URL che Anon Key di Supabase nel codice JS!');
return;
}
try {
supabaseClient = supabase.createClient(SUPABASE_URL, SUPABASE_KEY);
console.log('Client Supabase inizializzato correttamente.');
} catch (err) {
console.error('Errore durante l\'inizializzazione del client:', err);
}
}
function checkClient() {
if (!supabaseClient) {
console.log('Inizializza prima il client Supabase con URL e Anon Key!');
return false;
}
return true;
}
// 2. CREATE (Insert)
async function createRecord(event) {
event.preventDefault();
if (!checkClient()) return;
const title = document.getElementById('createTitle').value;
const description = document.getElementById('createDesc').value;
const { data, error } = await supabaseClient
.from('products')
.insert([{ name: title, description: description }])
.select();
if (error) {
console.error('Errore durante la CREATE:', error);
console.log('Errore: ' + error.message);
} else {
console.log('CREATE completata con successo:', data);
document.getElementById('createForm').reset();
readRecords();
}
}
// 3. READ (Select)
async function readRecords() {
if (!checkClient()) return;
const { data, error } = await supabaseClient
.from('products')
.select('*');
if (error) {
console.error('Errore durante la READ:', error);
console.log('Errore: ' + error.message);
} else {
console.log('READ completata:', data);
document.getElementById('outputRead').textContent = JSON.stringify(data, null, 2);
}
}
// 4. UPDATE
async function updateRecord(event) {
event.preventDefault();
if (!checkClient()) return;
const id = document.getElementById('updateId').value;
const title = document.getElementById('updateTitle').value;
const description = document.getElementById('updateDesc').value;
const { data, error } = await supabaseClient
.from('products')
.update({ name: title, description: description })
.eq('id', id)
.select();
if (error) {
console.error('Errore durante l\'UPDATE:', error);
console.log('Errore: ' + error.message);
} else {
console.log('UPDATE completata con successo:', data);
document.getElementById('updateForm').reset();
readRecords();
}
}
// 5. DELETE
async function deleteRecord(event) {
event.preventDefault();
if (!checkClient()) return;
const id = document.getElementById('deleteId').value;
const { data, error } = await supabaseClient
.from('products')
.delete()
.eq('id', id)
.select();
if (error) {
console.error('Errore durante la DELETE:', error);
console.log('Errore: ' + error.message);
} else {
console.log('DELETE completata con successo:', data);
document.getElementById('deleteForm').reset();
readRecords();
}
}
// Avvio inizializzazione
initSupabase();
</script>
</body>
</html>
auth.html
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Supabase Email & Password Auth</title>
<!-- Libreria Supabase JS via CDN -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
</head>
<body>
<h1>Supabase Authentication Example</h1>
<!-- STATO UTENTE CORRENTE -->
<section>
<h2>1. Stato Sessione</h2>
<div id="userInfo">Verifica stato in corso...</div>
<br>
<button onclick="checkUser()">Aggiorna Stato Utente</button>
<button onclick="handleSignOut()">Logout</button>
</section>
<hr>
<!-- REGISTRAZIONE -->
<section>
<h2>2. Registrazione (Sign Up)</h2>
<form id="signUpForm" onsubmit="handleSignUp(event)">
<label for="signUpEmail">Email:</label>
<input type="email" id="signUpEmail" required><br><br>
<label for="signUpPassword">Password:</label>
<input type="password" id="signUpPassword" required minlength="6"><br><br>
<button type="submit">Crea Account</button>
</form>
</section>
<hr>
<!-- LOGIN -->
<section>
<h2>3. Accesso (Sign In)</h2>
<form id="signInForm" onsubmit="handleSignIn(event)">
<label for="signInEmail">Email:</label>
<input type="email" id="signInEmail" required><br><br>
<label for="signInPassword">Password:</label>
<input type="password" id="signInPassword" required><br><br>
<button type="submit">Accedi</button>
</form>
</section>
<hr>
<!-- OUTPUT DEBUG -->
<section>
<h2>4. Risposta Supabase (Debug)</h2>
<pre id="outputLog">Nessuna operazione eseguita</pre>
</section>
<script>
let supabaseClient = null;
// 1. Inizializzazione Client
function initSupabase() {
const SUPABASE_URL = 'IL_TUO_SUPABASE_URL';
const SUPABASE_KEY = 'LA_TUA_SUPABASE_PUBLIC_KEY';
try {
supabaseClient = supabase.createClient(SUPABASE_URL, SUPABASE_KEY);
console.log('Client Supabase inizializzato.');
// Ascolta i cambiamenti di stato dell'autenticazione in tempo reale
supabaseClient.auth.onAuthStateChange((event, session) => {
console.log('Evento Auth:', event);
updateUI(session?.user || null);
});
checkUser();
} catch (err) {
console.error('Errore inizializzazione client:', err);
}
}
function checkClient() {
if (!supabaseClient) {
alert('Client Supabase non inizializzato!');
return false;
}
return true;
}
// 2. Controllo Stato Sessione
async function checkUser() {
if (!checkClient()) return;
const { data: { user }, error } = await supabaseClient.auth.getUser();
if (error && error.name !== 'AuthSessionMissingError') {
console.error('Errore recupero utente:', error);
}
updateUI(user);
}
function updateUI(user) {
const userInfoEl = document.getElementById('userInfo');
if (user) {
userInfoEl.innerHTML = `<strong>Autenticato come:</strong> ${user.email} <br><strong>ID Utente:</strong> <code>${user.id}</code>`;
} else {
userInfoEl.innerHTML = '<em>Nessun utente autenticato.</em>';
}
}
function logOutput(data) {
document.getElementById('outputLog').textContent = JSON.stringify(data, null, 2);
}
// 3. Registrazione (signUp)
async function handleSignUp(event) {
event.preventDefault();
if (!checkClient()) return;
const email = document.getElementById('signUpEmail').value;
const password = document.getElementById('signUpPassword').value;
const { data, error } = await supabaseClient.auth.signUp({
email: email,
password: password
});
if (error) {
alert('Errore Sign Up: ' + error.message);
logOutput(error);
} else {
alert('Registrazione effettuata! Se la conferma email è attiva sul tuo progetto Supabase, controlla la tua casella di posta.');
logOutput(data);
document.getElementById('signUpForm').reset();
}
}
// 4. Login (signInWithPassword)
async function handleSignIn(event) {
event.preventDefault();
if (!checkClient()) return;
const email = document.getElementById('signInEmail').value;
const password = document.getElementById('signInPassword').value;
const { data, error } = await supabaseClient.auth.signInWithPassword({
email: email,
password: password
});
if (error) {
alert('Errore Sign In: ' + error.message);
logOutput(error);
} else {
alert('Login effettuato con successo!');
logOutput(data);
document.getElementById('signInForm').reset();
}
}
// 5. Logout (signOut)
async function handleSignOut() {
if (!checkClient()) return;
const { error } = await supabaseClient.auth.signOut();
if (error) {
alert('Errore Logout: ' + error.message);
logOutput(error);
} else {
alert('Logout completato!');
logOutput({ status: 'Logged out successfully' });
}
}
// Avvio automatizzato
initSupabase();
</script>
</body>
</html>
Una volta fatto ciò puoi eseguire il codice con un server web locale, di cui mostro i passaggi per l'installazione in un precedente video, per provarlo e vedere se funziona correttamente.
Se non funziona
Controlla questi punti:
- Verifica di aver installato ed eseguito il codice sorgente con un server web locale.
- Verifica che
SUPABASE_URLe la chiave pubblica siano corrette. - Controlla che la tabella
productsesista e abbia le colonnenameedescription. - Se visualizzi
Failed to fetch, verifica la connessione internet e l'URL del progetto Supabase. - Controlla le policy RLS: disattivate in questo tutorial per scopi didattici, non disattivare mai le RLS in ambienti di produzione se previste nell'architettura.
- Apri il file tramite un server locale o direttamente nel browser.
Puoi utilizzare LLM e coding agent per trovare errori. Oppure contattami per richiedere supporto allo sviluppo.