vamos
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
|
||||
// Estado global compartido para auth
|
||||
const authChecked = ref(false)
|
||||
@@ -6,12 +6,16 @@ const isAuthenticated = ref(false)
|
||||
const isCheckingAuth = ref(false)
|
||||
const lastCheckTime = ref(0)
|
||||
|
||||
// Listener para cambios de autenticación desde otras tabs/ventanas
|
||||
let visibilityChangeListener: (() => void) | null = null
|
||||
let focusListener: (() => void) | null = null
|
||||
|
||||
export const useAuth = () => {
|
||||
const checkAuth = async (force = false) => {
|
||||
// Evitar chequeos duplicados (cache de 30 segundos)
|
||||
// Evitar chequeos duplicados (cache de 10 segundos, reducido)
|
||||
const now = Date.now()
|
||||
if (!force && isCheckingAuth.value) return
|
||||
if (!force && authChecked.value && now - lastCheckTime.value < 30000) {
|
||||
if (!force && authChecked.value && now - lastCheckTime.value < 10000) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -22,23 +26,23 @@ export const useAuth = () => {
|
||||
const response = await fetch('/api/music', {
|
||||
method: 'HEAD', // Solo headers, no body
|
||||
credentials: 'include', // Include cookies for auth
|
||||
cache: 'no-store', // No cachear la respuesta
|
||||
signal: AbortSignal.timeout(5000) // 5s timeout
|
||||
})
|
||||
|
||||
// Si responde 200, estamos autenticados
|
||||
// Si responde 401/403, no estamos autenticados
|
||||
const wasAuthenticated = isAuthenticated.value
|
||||
isAuthenticated.value = response.ok
|
||||
authChecked.value = true
|
||||
lastCheckTime.value = now
|
||||
|
||||
console.log('[Auth] Status:', isAuthenticated.value ? 'authenticated' : 'unauthenticated')
|
||||
// Log cambios de estado
|
||||
if (wasAuthenticated !== isAuthenticated.value) {
|
||||
console.log('[Auth] Status changed:', isAuthenticated.value ? 'authenticated' : 'unauthenticated')
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[Auth] Failed to check authentication status:', error)
|
||||
// En caso de error de red, mantenemos el último estado conocido si existe
|
||||
// Solo marcamos como no autenticado si es el primer chequeo
|
||||
if (!authChecked.value) {
|
||||
isAuthenticated.value = false
|
||||
}
|
||||
// En caso de error de red, marcamos como no autenticado
|
||||
isAuthenticated.value = false
|
||||
authChecked.value = true
|
||||
lastCheckTime.value = now
|
||||
} finally {
|
||||
@@ -46,24 +50,77 @@ export const useAuth = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const triggerAuth = () => {
|
||||
console.log('[Auth] Redirecting to trigger Authentik...')
|
||||
// Redirige a la página principal para que Authentik intercepte
|
||||
// Si ya estamos en /, forzamos reload
|
||||
if (window.location.pathname === '/') {
|
||||
window.location.reload()
|
||||
} else {
|
||||
window.location.href = '/'
|
||||
const triggerAuth = async () => {
|
||||
console.log('[Auth] Triggering authentication flow...')
|
||||
|
||||
// Primero, hacemos una request al endpoint protegido para forzar
|
||||
// que Authentik nos redirija a su página de login
|
||||
try {
|
||||
const response = await fetch('/api/music', {
|
||||
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 = () => {
|
||||
// Helper para marcar como no autenticado (útil cuando detectamos 401/403)
|
||||
console.log('[Auth] Marking as unauthenticated')
|
||||
isAuthenticated.value = false
|
||||
authChecked.value = true
|
||||
lastCheckTime.value = Date.now()
|
||||
}
|
||||
|
||||
const setupVisibilityListener = () => {
|
||||
// Re-chequea auth cuando la pestaña vuelve a ser visible
|
||||
// (útil si el usuario se autentica en otra pestaña)
|
||||
if (typeof document !== 'undefined' && !visibilityChangeListener) {
|
||||
visibilityChangeListener = () => {
|
||||
if (!document.hidden) {
|
||||
console.log('[Auth] Tab visible again, checking auth...')
|
||||
checkAuth(true)
|
||||
}
|
||||
}
|
||||
document.addEventListener('visibilitychange', visibilityChangeListener)
|
||||
}
|
||||
|
||||
// También chequea cuando la ventana recibe foco
|
||||
if (typeof window !== 'undefined' && !focusListener) {
|
||||
focusListener = () => {
|
||||
console.log('[Auth] Window focused, checking auth...')
|
||||
checkAuth(true)
|
||||
}
|
||||
window.addEventListener('focus', focusListener)
|
||||
}
|
||||
}
|
||||
|
||||
const cleanupListeners = () => {
|
||||
if (visibilityChangeListener) {
|
||||
document.removeEventListener('visibilitychange', visibilityChangeListener)
|
||||
visibilityChangeListener = null
|
||||
}
|
||||
if (focusListener) {
|
||||
window.removeEventListener('focus', focusListener)
|
||||
focusListener = null
|
||||
}
|
||||
}
|
||||
|
||||
const authStatus = computed(() => {
|
||||
if (!authChecked.value) return 'unknown'
|
||||
return isAuthenticated.value ? 'authenticated' : 'unauthenticated'
|
||||
@@ -76,6 +133,8 @@ export const useAuth = () => {
|
||||
authStatus,
|
||||
checkAuth,
|
||||
triggerAuth,
|
||||
markUnauthenticated
|
||||
markUnauthenticated,
|
||||
setupVisibilityListener,
|
||||
cleanupListeners
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user