fix: auth flow - logout nuclear, router redirige admin a panel, login sin bloqueo BD
This commit is contained in:
@ -146,9 +146,8 @@ const openReportModal = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
authStore.logout()
|
|
||||||
showMenu.value = false
|
showMenu.value = false
|
||||||
router.push('/login')
|
authStore.logout()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -17,16 +17,18 @@ const authStore = useAuthStore()
|
|||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
console.log('Iniciando Login con correo...')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authStore.login(email.value.trim().toLowerCase(), password.value)
|
await authStore.login(email.value.trim().toLowerCase(), password.value)
|
||||||
|
|
||||||
// Esperar a que el perfil se cargue globalmente para saber a qué pantalla navegar
|
// Esperar hasta que el perfil esté cargado (máx 3 segundos)
|
||||||
setTimeout(() => {
|
let attempts = 0
|
||||||
const r = authStore.role || 'PASSENGER'
|
while (!authStore.role && attempts < 30) {
|
||||||
navigateByUserRole(r)
|
await new Promise(res => setTimeout(res, 100))
|
||||||
}, 800)
|
attempts++
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateByUserRole(authStore.role || 'PASSENGER')
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Error Login detallado:', error)
|
console.error('Error Login detallado:', error)
|
||||||
|
|||||||
@ -147,12 +147,13 @@ const router = createRouter({
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to, _from, next) => {
|
router.beforeEach(async (to, _from, next) => {
|
||||||
// Rutas públicas: siempre pasan sin verificación
|
// Rutas completamente públicas (splash, login)
|
||||||
if (!to.meta.requiresAuth && !to.meta.role) {
|
const publicRoutes = ['/login', '/splash', '/']
|
||||||
|
if (publicRoutes.includes(to.path)) {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leer sesión activa de Supabase (sustituye el viejo localStorage)
|
// Leer sesión activa de Supabase
|
||||||
const { data: { session } } = await supabase.auth.getSession()
|
const { data: { session } } = await supabase.auth.getSession()
|
||||||
|
|
||||||
// Ruta protegida sin sesión → redirige a login
|
// Ruta protegida sin sesión → redirige a login
|
||||||
@ -160,8 +161,8 @@ router.beforeEach(async (to, _from, next) => {
|
|||||||
return next('/login')
|
return next('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ruta con restricción de rol → verificar en la BD
|
// Si hay sesión, obtener el rol real del usuario
|
||||||
if (to.meta.role && session) {
|
if (session) {
|
||||||
const { data: profile } = await supabase
|
const { data: profile } = await supabase
|
||||||
.from('users')
|
.from('users')
|
||||||
.select('role')
|
.select('role')
|
||||||
@ -169,18 +170,27 @@ router.beforeEach(async (to, _from, next) => {
|
|||||||
.single()
|
.single()
|
||||||
|
|
||||||
const userRole = profile?.role?.toUpperCase() || 'PASSENGER'
|
const userRole = profile?.role?.toUpperCase() || 'PASSENGER'
|
||||||
|
|
||||||
|
// Si el admin entra a rutas de pasajero → redirigir al panel admin
|
||||||
|
const passengerRoutes = ['/map', '/schedule', '/discover', '/transport', '/favorites', '/profile', '/coupons']
|
||||||
|
if (userRole === 'ADMIN' && passengerRoutes.some(r => to.path.startsWith(r))) {
|
||||||
|
return next('/admin')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ruta con restricción de rol → verificar permiso
|
||||||
|
if (to.meta.role) {
|
||||||
const allowedRoles = Array.isArray(to.meta.role)
|
const allowedRoles = Array.isArray(to.meta.role)
|
||||||
? (to.meta.role as string[]).map(r => r.toUpperCase())
|
? (to.meta.role as string[]).map(r => r.toUpperCase())
|
||||||
: [(to.meta.role as string).toUpperCase()]
|
: [(to.meta.role as string).toUpperCase()]
|
||||||
|
|
||||||
if (!allowedRoles.includes(userRole)) {
|
if (!allowedRoles.includes(userRole)) {
|
||||||
// Redirigir a la vista correcta según su rol real
|
|
||||||
if (userRole === 'ADMIN') return next('/admin')
|
if (userRole === 'ADMIN') return next('/admin')
|
||||||
else if (userRole === 'DRIVER') return next('/driver')
|
else if (userRole === 'DRIVER') return next('/driver')
|
||||||
else if (userRole === 'PROMOTER') return next('/promoter')
|
else if (userRole === 'PROMOTER') return next('/promoter')
|
||||||
else return next('/map')
|
else return next('/map')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -36,16 +36,46 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function login(email: string, pass: string) {
|
async function login(email: string, pass: string) {
|
||||||
// Use standard Supabase signIn
|
const { data, error } = await supabase.auth.signInWithPassword({ email, password: pass })
|
||||||
const { error } = await supabase.auth.signInWithPassword({ email, password: pass })
|
|
||||||
if (error) throw new Error(error.message)
|
if (error) throw new Error(error.message)
|
||||||
|
|
||||||
|
if (data.user) {
|
||||||
|
// Establecer sesión y rol inmediatamente desde el JWT (sin esperar BD)
|
||||||
|
userSession.value = data.session
|
||||||
|
// Usar user_metadata como perfil temporal para que el rol esté listo al instante
|
||||||
|
userProfile.value = {
|
||||||
|
id: data.user.id,
|
||||||
|
email: data.user.email,
|
||||||
|
full_name: data.user.user_metadata?.full_name || data.user.email,
|
||||||
|
role: data.user.user_metadata?.role || 'PASSENGER'
|
||||||
|
}
|
||||||
|
// Cargar perfil completo de BD en background (sin bloquear navegación)
|
||||||
|
supabase.from('users').select('*').eq('id', data.user.id).single()
|
||||||
|
.then(({ data: profile }) => { if (profile) userProfile.value = profile })
|
||||||
|
.catch(() => { })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logout() {
|
function logout() {
|
||||||
await supabase.auth.signOut()
|
// Limpiar estado de Pinia inmediatamente
|
||||||
userSession.value = null
|
userSession.value = null
|
||||||
userProfile.value = null
|
userProfile.value = null
|
||||||
window.location.href = '/'
|
|
||||||
|
// Limpiar TODA la sesión del navegador sin esperar a Supabase
|
||||||
|
localStorage.clear()
|
||||||
|
sessionStorage.clear()
|
||||||
|
|
||||||
|
// Limpiar IndexedDB donde Supabase guarda tokens
|
||||||
|
try {
|
||||||
|
indexedDB.deleteDatabase('supabase-js-auth')
|
||||||
|
indexedDB.deleteDatabase('supabase')
|
||||||
|
} catch (_) { }
|
||||||
|
|
||||||
|
// Llamar signOut en background (sin await - no bloqueamos)
|
||||||
|
supabase.auth.signOut().catch(() => { })
|
||||||
|
|
||||||
|
// Redirigir forzando recarga completa del navegador
|
||||||
|
window.location.replace('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user