vamos2
This commit is contained in:
@@ -36,15 +36,19 @@ const musicStore = useMusicStore()
|
|||||||
|
|
||||||
// Check auth on mount and setup listeners
|
// Check auth on mount and setup listeners
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await checkAuth(true)
|
// Asumimos autenticado inicialmente (si la página cargó, pasamos Authentik)
|
||||||
|
// Solo verificamos para confirmar
|
||||||
|
await checkAuth(false)
|
||||||
setupVisibilityListener()
|
setupVisibilityListener()
|
||||||
|
|
||||||
// Chequea auth cada 30 segundos mientras la pestaña está activa
|
// Polling más inteligente: solo si estamos autenticados
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (!document.hidden) {
|
if (!document.hidden && isAuthenticated.value) {
|
||||||
checkAuth()
|
// Solo hace polling si creemos estar autenticados
|
||||||
|
// Evita spam de requests cuando ya sabemos que no estamos autenticados
|
||||||
|
checkAuth(false)
|
||||||
}
|
}
|
||||||
}, 30000)
|
}, 60000) // 60 segundos (menos agresivo)
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
clearInterval(interval)
|
clearInterval(interval)
|
||||||
@@ -104,9 +108,9 @@ const statusText = computed(() => {
|
|||||||
case 'authenticated':
|
case 'authenticated':
|
||||||
return 'Conectado'
|
return 'Conectado'
|
||||||
case 'unauthenticated':
|
case 'unauthenticated':
|
||||||
return 'Sin conexión'
|
return 'Reautenticar'
|
||||||
default:
|
default:
|
||||||
return 'Desconocido'
|
return 'Verificando...'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -115,11 +119,11 @@ const tooltipText = computed(() => {
|
|||||||
|
|
||||||
switch (authStatus.value) {
|
switch (authStatus.value) {
|
||||||
case 'authenticated':
|
case 'authenticated':
|
||||||
return 'Estás autenticado. Puedes descargar música.'
|
return 'Estás autenticado. Click para verificar estado.'
|
||||||
case 'unauthenticated':
|
case 'unauthenticated':
|
||||||
return 'No autenticado. Click para iniciar sesión.'
|
return 'Sesión expirada. Click para iniciar sesión de nuevo.'
|
||||||
default:
|
default:
|
||||||
return 'Estado de autenticación desconocido'
|
return 'Verificando estado de autenticación...'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -127,11 +131,11 @@ const handleClick = () => {
|
|||||||
if (isCheckingAuth.value) return
|
if (isCheckingAuth.value) return
|
||||||
|
|
||||||
if (authStatus.value === 'unauthenticated') {
|
if (authStatus.value === 'unauthenticated') {
|
||||||
// Redirect to trigger Authentik
|
// Forzar reload de la página para que Authentik intercepte
|
||||||
triggerAuth()
|
triggerAuth()
|
||||||
} else if (authStatus.value === 'authenticated') {
|
} else if (authStatus.value === 'authenticated') {
|
||||||
// Re-check auth status
|
// Re-check auth status (forzar, ignorar cache)
|
||||||
checkAuth()
|
checkAuth(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ref, computed, onUnmounted } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
// Estado global compartido para auth
|
// Estado global compartido para auth
|
||||||
const authChecked = ref(false)
|
const authChecked = ref(true) // Iniciamos como chequeado
|
||||||
const isAuthenticated = ref(false)
|
const isAuthenticated = ref(true) // Asumimos autenticado al inicio (si la página cargó, es porque pasamos Authentik)
|
||||||
const isCheckingAuth = ref(false)
|
const isCheckingAuth = ref(false)
|
||||||
const lastCheckTime = ref(0)
|
const lastCheckTime = ref(0)
|
||||||
|
|
||||||
@@ -12,10 +12,17 @@ let focusListener: (() => void) | null = null
|
|||||||
|
|
||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
const checkAuth = async (force = false) => {
|
const checkAuth = async (force = false) => {
|
||||||
// Evitar chequeos duplicados (cache de 10 segundos, reducido)
|
// Si ya sabemos que NO estamos autenticados, no hacer más requests
|
||||||
|
// (evita loops de CORS con Authentik redirects)
|
||||||
|
if (!isAuthenticated.value && !force) {
|
||||||
|
console.log('[Auth] Skipping check - already known to be unauthenticated')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evitar chequeos duplicados (cache de 30 segundos)
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
if (!force && isCheckingAuth.value) return
|
if (!force && isCheckingAuth.value) return
|
||||||
if (!force && authChecked.value && now - lastCheckTime.value < 10000) {
|
if (!force && authChecked.value && now - lastCheckTime.value < 30000) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +34,7 @@ export const useAuth = () => {
|
|||||||
method: 'HEAD', // Solo headers, no body
|
method: 'HEAD', // Solo headers, no body
|
||||||
credentials: 'include', // Include cookies for auth
|
credentials: 'include', // Include cookies for auth
|
||||||
cache: 'no-store', // No cachear la respuesta
|
cache: 'no-store', // No cachear la respuesta
|
||||||
|
redirect: 'error', // No seguir redirects (error si Authentik intenta redirigir)
|
||||||
signal: AbortSignal.timeout(5000) // 5s timeout
|
signal: AbortSignal.timeout(5000) // 5s timeout
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -39,44 +47,35 @@ export const useAuth = () => {
|
|||||||
if (wasAuthenticated !== isAuthenticated.value) {
|
if (wasAuthenticated !== isAuthenticated.value) {
|
||||||
console.log('[Auth] Status changed:', isAuthenticated.value ? 'authenticated' : 'unauthenticated')
|
console.log('[Auth] Status changed:', isAuthenticated.value ? 'authenticated' : 'unauthenticated')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.warn('[Auth] Failed to check authentication status:', error)
|
// TypeError: Failed to fetch = probablemente redirect de Authentik (no autenticado)
|
||||||
// En caso de error de red, marcamos como no autenticado
|
// o error de red real
|
||||||
isAuthenticated.value = false
|
console.warn('[Auth] Check failed:', error.message)
|
||||||
authChecked.value = true
|
|
||||||
|
// Si el error es por redirect (Authentik intenta redirigir a login), no estamos autenticados
|
||||||
|
if (error.message && error.message.includes('redirect')) {
|
||||||
|
const wasAuthenticated = isAuthenticated.value
|
||||||
|
isAuthenticated.value = false
|
||||||
|
authChecked.value = true
|
||||||
|
if (wasAuthenticated) {
|
||||||
|
console.log('[Auth] Status changed: unauthenticated (redirect detected)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Si no, mantenemos el estado actual (puede ser error de red temporal)
|
||||||
|
|
||||||
lastCheckTime.value = now
|
lastCheckTime.value = now
|
||||||
} finally {
|
} finally {
|
||||||
isCheckingAuth.value = false
|
isCheckingAuth.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerAuth = async () => {
|
const triggerAuth = () => {
|
||||||
console.log('[Auth] Triggering authentication flow...')
|
console.log('[Auth] Triggering authentication flow - forcing page reload...')
|
||||||
|
|
||||||
// Primero, hacemos una request al endpoint protegido para forzar
|
// Simplemente recargamos la página completamente
|
||||||
// que Authentik nos redirija a su página de login
|
// Si no estamos autenticados, Authentik interceptará y redirigirá al login
|
||||||
try {
|
// Si ya estamos autenticados, la página se recarga normalmente
|
||||||
const response = await fetch('/api/music', {
|
window.location.reload()
|
||||||
method: 'GET',
|
|
||||||
credentials: 'include',
|
|
||||||
redirect: 'manual' // No seguir redirects automáticamente
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!response.ok && (response.status === 401 || response.status === 403)) {
|
|
||||||
// Si obtenemos 401/403, forzamos un reload completo de la página
|
|
||||||
// para que Traefik + Authentik intercepten y redirijan al login
|
|
||||||
console.log('[Auth] Unauthorized - forcing full page reload to trigger auth')
|
|
||||||
window.location.href = window.location.href
|
|
||||||
} else if (response.ok) {
|
|
||||||
// Si la respuesta es OK, ya estamos autenticados
|
|
||||||
console.log('[Auth] Already authenticated')
|
|
||||||
await checkAuth(true)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[Auth] Error triggering auth:', error)
|
|
||||||
// En caso de error, forzamos reload de todas formas
|
|
||||||
window.location.href = window.location.href
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const markUnauthenticated = () => {
|
const markUnauthenticated = () => {
|
||||||
@@ -92,9 +91,11 @@ export const useAuth = () => {
|
|||||||
// (útil si el usuario se autentica en otra pestaña)
|
// (útil si el usuario se autentica en otra pestaña)
|
||||||
if (typeof document !== 'undefined' && !visibilityChangeListener) {
|
if (typeof document !== 'undefined' && !visibilityChangeListener) {
|
||||||
visibilityChangeListener = () => {
|
visibilityChangeListener = () => {
|
||||||
if (!document.hidden) {
|
if (!document.hidden && isAuthenticated.value) {
|
||||||
|
// Solo chequear si creemos estar autenticados
|
||||||
|
// (evita spam de requests fallidas)
|
||||||
console.log('[Auth] Tab visible again, checking auth...')
|
console.log('[Auth] Tab visible again, checking auth...')
|
||||||
checkAuth(true)
|
checkAuth(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener('visibilitychange', visibilityChangeListener)
|
document.addEventListener('visibilitychange', visibilityChangeListener)
|
||||||
@@ -103,8 +104,11 @@ export const useAuth = () => {
|
|||||||
// También chequea cuando la ventana recibe foco
|
// También chequea cuando la ventana recibe foco
|
||||||
if (typeof window !== 'undefined' && !focusListener) {
|
if (typeof window !== 'undefined' && !focusListener) {
|
||||||
focusListener = () => {
|
focusListener = () => {
|
||||||
console.log('[Auth] Window focused, checking auth...')
|
if (isAuthenticated.value) {
|
||||||
checkAuth(true)
|
// Solo chequear si creemos estar autenticados
|
||||||
|
console.log('[Auth] Window focused, checking auth...')
|
||||||
|
checkAuth(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
window.addEventListener('focus', focusListener)
|
window.addEventListener('focus', focusListener)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user