diff --git a/clear-auth-script.js b/clear-auth-script.js new file mode 100644 index 0000000..69bb943 --- /dev/null +++ b/clear-auth-script.js @@ -0,0 +1,49 @@ +// Script de nettoyage d'authentification Supabase +// À exécuter dans la console du navigateur (F12 > Console) + +console.log('🧹 Début du nettoyage d\'authentification Supabase...'); + +// 1. Nettoyer localStorage +const keysToRemove = []; +for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key && (key.includes('supabase') || key.includes('sb-'))) { + keysToRemove.push(key); + } +} + +keysToRemove.forEach(key => { + localStorage.removeItem(key); + console.log('🗑️ Supprimé:', key); +}); + +// 2. Nettoyer sessionStorage +const sessionKeysToRemove = []; +for (let i = 0; i < sessionStorage.length; i++) { + const key = sessionStorage.key(i); + if (key && (key.includes('supabase') || key.includes('sb-'))) { + sessionKeysToRemove.push(key); + } +} + +sessionKeysToRemove.forEach(key => { + sessionStorage.removeItem(key); + console.log('🗑️ Supprimé (session):', key); +}); + +// 3. Nettoyer les cookies liés à Supabase +document.cookie.split(";").forEach(function(c) { + document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/"); +}); + +console.log('✅ Nettoyage terminé !'); +console.log('📋 Résumé:'); +console.log(`- ${keysToRemove.length} clés localStorage supprimées`); +console.log(`- ${sessionKeysToRemove.length} clés sessionStorage supprimées`); +console.log('- Cookies nettoyés'); +console.log(''); +console.log('🔄 Rechargez maintenant la page (F5) et essayez de vous reconnecter.'); + +// Optionnel: recharger automatiquement +// window.location.reload(); + diff --git a/src/app/api/clear-auth/route.ts b/src/app/api/clear-auth/route.ts new file mode 100644 index 0000000..6bf858d --- /dev/null +++ b/src/app/api/clear-auth/route.ts @@ -0,0 +1,38 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { supabase } from '@/lib/supabase'; + +export async function POST(request: NextRequest) { + try { + console.log('🧹 Nettoyage de l\'état d\'authentification...'); + + // Déconnexion forcée + const { error } = await supabase.auth.signOut(); + + if (error) { + console.warn('⚠️ Erreur lors de la déconnexion:', error.message); + } else { + console.log('✅ Déconnexion réussie'); + } + + // Nettoyer le localStorage côté client + return NextResponse.json({ + success: true, + message: 'État d\'authentification nettoyé', + instructions: [ + '1. Ouvrez les outils de développement (F12)', + '2. Allez dans l\'onglet Application/Storage', + '3. Supprimez toutes les entrées liées à Supabase dans localStorage', + '4. Rechargez la page', + '5. Essayez de vous reconnecter' + ] + }); + + } catch (error: any) { + console.error('❌ Erreur lors du nettoyage:', error); + return NextResponse.json( + { error: `Erreur lors du nettoyage: ${error.message}` }, + { status: 500 } + ); + } +} + diff --git a/src/app/clear-auth/page.tsx b/src/app/clear-auth/page.tsx new file mode 100644 index 0000000..1aecd25 --- /dev/null +++ b/src/app/clear-auth/page.tsx @@ -0,0 +1,186 @@ +'use client'; + +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Alert, AlertDescription } from '@/components/ui/alert'; +import { Loader2, CheckCircle, AlertCircle, Trash2, RefreshCw } from 'lucide-react'; + +export default function ClearAuthPage() { + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + const [localStorageCleared, setLocalStorageCleared] = useState(false); + + const clearServerAuth = async () => { + setLoading(true); + setError(''); + setSuccess(false); + + try { + const response = await fetch('/api/clear-auth', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const result = await response.json(); + + if (result.success) { + setSuccess(true); + } else { + setError(result.error || 'Erreur lors du nettoyage serveur'); + } + } catch (error: any) { + setError(error.message || 'Erreur lors du nettoyage serveur'); + } finally { + setLoading(false); + } + }; + + const clearLocalStorage = () => { + try { + // Supprimer toutes les clés liées à Supabase + const keysToRemove = []; + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key && (key.includes('supabase') || key.includes('sb-'))) { + keysToRemove.push(key); + } + } + + keysToRemove.forEach(key => { + localStorage.removeItem(key); + }); + + setLocalStorageCleared(true); + console.log('🧹 localStorage nettoyé:', keysToRemove); + } catch (error) { + console.error('❌ Erreur lors du nettoyage localStorage:', error); + setError('Erreur lors du nettoyage localStorage'); + } + }; + + const reloadPage = () => { + window.location.reload(); + }; + + return ( +
+
+
+

+ 🧹 Nettoyage d'Authentification +

+

+ Résoudre les problèmes de session Supabase +

+
+ + + + + + Nettoyer l'état d'authentification + + + + + + + Problème détecté : AuthSessionMissingError +
+ Cette erreur indique que Supabase ne peut pas récupérer votre session d'authentification. +
+ Solution : Nettoyez l'état d'authentification et reconnectez-vous. +
+
+ +
+
+ + + +
+ + +
+ + {error && ( + + + {error} + + )} + + {success && ( + + + + Nettoyage serveur réussi ! Maintenant nettoyez le localStorage et rechargez la page. + + + )} + + {localStorageCleared && ( + + + + localStorage nettoyé ! Rechargez maintenant la page pour finaliser. + + + )} + +
+

📋 Instructions détaillées :

+
    +
  1. Cliquez sur "Nettoyer côté serveur"
  2. +
  3. Cliquez sur "Nettoyer localStorage"
  4. +
  5. Cliquez sur "Recharger la page"
  6. +
  7. Allez sur /debug-auth pour vous reconnecter
  8. +
  9. Ou allez directement sur /admin
  10. +
+
+ +
+

+ 💡 Après le nettoyage : +

+
    +
  • Votre session sera complètement réinitialisée
  • +
  • Vous devrez vous reconnecter avec vos identifiants admin
  • +
  • Utilisez la page /debug-auth pour une connexion rapide
  • +
  • Ou connectez-vous normalement sur /admin
  • +
+
+
+
+
+
+ ); +} + diff --git a/src/components/AuthGuard.tsx b/src/components/AuthGuard.tsx index d02179c..8c5303b 100644 --- a/src/components/AuthGuard.tsx +++ b/src/components/AuthGuard.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { authService } from '@/lib/auth'; +import { supabase } from '@/lib/supabase'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; @@ -34,10 +35,14 @@ export default function AuthGuard({ children, requireSuperAdmin = false }: AuthG const checkAuth = async () => { try { setIsLoading(true); + console.log('🔍 AuthGuard: Vérification de l\'authentification...'); - // Vérifier si l'utilisateur est connecté - const user = await authService.getCurrentUser(); - if (!user) { + // Vérifier si l'utilisateur est connecté directement avec supabase + const { data: { user }, error: userError } = await supabase.auth.getUser(); + console.log('👤 AuthGuard: Utilisateur actuel:', user ? user.email : 'Aucun'); + + if (userError || !user) { + console.log('❌ AuthGuard: Aucun utilisateur connecté'); setIsAuthenticated(false); setIsAuthorized(false); setShowLogin(true); @@ -45,21 +50,39 @@ export default function AuthGuard({ children, requireSuperAdmin = false }: AuthG } setIsAuthenticated(true); + console.log('✅ AuthGuard: Utilisateur authentifié'); + + // Vérifier les permissions directement + const { data: permissions, error: permissionsError } = await supabase + .from('user_permissions') + .select('*') + .eq('user_id', user.id) + .single(); + + if (permissionsError) { + console.error('❌ AuthGuard: Erreur permissions:', permissionsError); + setIsAuthorized(false); + setError('Erreur lors de la vérification des permissions'); + return; + } - // Vérifier les permissions if (requireSuperAdmin) { - const isSuperAdmin = await authService.isSuperAdmin(); + const isSuperAdmin = permissions.is_super_admin; + console.log('🔐 AuthGuard: Super Admin:', isSuperAdmin); setIsAuthorized(isSuperAdmin); } else { - const isAdmin = await authService.isAdmin(); + const isAdmin = permissions.is_admin; + console.log('🔐 AuthGuard: Admin:', isAdmin); setIsAuthorized(isAdmin); } if (!isAuthorized) { setError('Vous n\'avez pas les permissions nécessaires pour accéder à cette page.'); + } else { + console.log('✅ AuthGuard: Permissions vérifiées, accès autorisé'); } } catch (error) { - console.error('Erreur lors de la vérification d\'authentification:', error); + console.error('❌ AuthGuard: Erreur lors de la vérification d\'authentification:', error); setIsAuthenticated(false); setIsAuthorized(false); setShowLogin(true); @@ -74,11 +97,53 @@ export default function AuthGuard({ children, requireSuperAdmin = false }: AuthG setIsLoggingIn(true); try { - await authService.signIn(email, password); - await checkAuth(); + console.log('🔐 AuthGuard: Tentative de connexion directe...'); + + // Utiliser directement supabase.auth.signInWithPassword comme dans admin-login + const { data, error: loginError } = await supabase.auth.signInWithPassword({ + email, + password, + }); + + if (loginError) { + console.error('❌ AuthGuard: Erreur de connexion:', loginError); + setError(`Erreur: ${loginError.message}`); + return; + } + + console.log('✅ AuthGuard: Connexion réussie, vérification des permissions...'); + + // Vérifier les permissions directement + const { data: permissions, error: permissionsError } = await supabase + .from('user_permissions') + .select('*') + .eq('user_id', data.user.id) + .single(); + + if (permissionsError) { + console.error('❌ AuthGuard: Erreur permissions:', permissionsError); + setError('Erreur lors de la vérification des permissions'); + return; + } + + if (requireSuperAdmin && !permissions.is_super_admin) { + setError('Vous n\'avez pas les permissions de super administrateur'); + return; + } else if (!requireSuperAdmin && !permissions.is_admin) { + setError('Vous n\'avez pas les permissions administrateur'); + return; + } + + console.log('✅ AuthGuard: Permissions vérifiées, accès autorisé'); + + // Mettre à jour les états + setIsAuthenticated(true); + setIsAuthorized(true); + setShowLogin(false); + } catch (error: any) { - console.error('Erreur de connexion:', error); - setError(error.message || 'Erreur lors de la connexion'); + console.error('❌ AuthGuard: Exception:', error); + setError(`Erreur: ${error.message}`); } finally { setIsLoggingIn(false); } @@ -86,7 +151,7 @@ export default function AuthGuard({ children, requireSuperAdmin = false }: AuthG const handleLogout = async () => { try { - await authService.signOut(); + await supabase.auth.signOut(); setIsAuthenticated(false); setIsAuthorized(false); setShowLogin(true); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 213a1b7..a690a4e 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -12,9 +12,26 @@ export interface UserPermissions { export const authService = { // Vérifier si l'utilisateur actuel est connecté async getCurrentUser() { - const { data: { user }, error } = await supabase.auth.getUser(); - if (error) throw error; - return user; + try { + const { data: { user }, error } = await supabase.auth.getUser(); + if (error) { + console.error('❌ Erreur getCurrentUser:', error); + // Si c'est une erreur de session manquante, retourner null au lieu de throw + if (error.message?.includes('Auth session missing') || error.message?.includes('session_not_found')) { + console.log('🔍 Session manquante, utilisateur non connecté'); + return null; + } + throw error; + } + return user; + } catch (error: any) { + console.error('❌ Exception getCurrentUser:', error); + // Gérer les erreurs de session manquante + if (error.message?.includes('Auth session missing') || error.message?.includes('session_not_found')) { + return null; + } + throw error; + } }, // Vérifier si l'utilisateur actuel est admin @@ -87,18 +104,56 @@ export const authService = { // Connexion async signIn(email: string, password: string) { - const { data, error } = await supabase.auth.signInWithPassword({ - email, - password, - }); - if (error) throw error; - return data; + try { + console.log('🔐 Tentative de connexion pour:', email); + + const { data, error } = await supabase.auth.signInWithPassword({ + email, + password, + }); + + if (error) { + console.error('❌ Erreur de connexion:', error); + throw error; + } + + console.log('✅ Connexion réussie pour:', email); + return data; + } catch (error) { + console.error('❌ Exception lors de la connexion:', error); + throw error; + } }, // Déconnexion async signOut() { - const { error } = await supabase.auth.signOut(); - if (error) throw error; + try { + // Déconnexion standard + const { error } = await supabase.auth.signOut(); + if (error) throw error; + + // Nettoyage supplémentaire pour éviter les problèmes de session + // Supprimer tous les tokens du localStorage + if (typeof window !== 'undefined') { + const keys = Object.keys(localStorage); + keys.forEach(key => { + if (key.startsWith('sb-') || key.includes('supabase')) { + localStorage.removeItem(key); + } + }); + + // Supprimer aussi du sessionStorage + const sessionKeys = Object.keys(sessionStorage); + sessionKeys.forEach(key => { + if (key.startsWith('sb-') || key.includes('supabase')) { + sessionStorage.removeItem(key); + } + }); + } + } catch (error) { + console.error('Erreur lors de la déconnexion:', error); + throw error; + } }, // Inscription (pour les tests)