All checks were successful
Build and Deploy Nuxt / build (push) Successful in 2m26s
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { ADMIN_TOKEN_COOKIE, ApiError } from './useApi'
|
|
|
|
export interface AdminUser {
|
|
username: string
|
|
}
|
|
|
|
const TOKEN_TTL_SECONDS = 60 * 60 * 12
|
|
|
|
export default function useAuth() {
|
|
const config = useRuntimeConfig()
|
|
const baseUrl = `${config.public.apiBaseUrl.replace(/\/+$/, '')}/api`
|
|
|
|
const token = useCookie<string | null>(ADMIN_TOKEN_COOKIE, {
|
|
maxAge: TOKEN_TTL_SECONDS,
|
|
sameSite: 'lax',
|
|
path: '/',
|
|
default: () => null
|
|
})
|
|
const user = useState<AdminUser | null>('admin-user', () => null)
|
|
|
|
const isAuthenticated = computed(() => !!token.value)
|
|
|
|
const login = async (username: string, password: string) => {
|
|
const res = await fetch(`${baseUrl}/auth/login`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ username, password })
|
|
})
|
|
const data = await res.json().catch(() => ({}))
|
|
if (!res.ok) throw new ApiError(data.error || 'Login failed', res.status)
|
|
token.value = data.token
|
|
user.value = { username: data.username }
|
|
return data
|
|
}
|
|
|
|
const logout = () => {
|
|
token.value = null
|
|
user.value = null
|
|
}
|
|
|
|
// Validates the stored token against the backend; logs out on failure.
|
|
const fetchMe = async () => {
|
|
if (!token.value) return null
|
|
try {
|
|
const res = await fetch(`${baseUrl}/auth/me`, {
|
|
headers: { Authorization: `Bearer ${token.value}` }
|
|
})
|
|
if (res.status === 401) {
|
|
logout()
|
|
return null
|
|
}
|
|
if (!res.ok) throw new Error('auth check failed')
|
|
const data = await res.json()
|
|
user.value = { username: data.username }
|
|
return data
|
|
} catch (e) {
|
|
return null
|
|
}
|
|
}
|
|
|
|
return { token, user, isAuthenticated, login, logout, fetchMe }
|
|
}
|