feat: implement auth middleware, user sync, and token state persistence
- Define useAuth composable logic with syncUser, handleLoginSuccess, and logout methods - Add auth.ts and guest.ts route middlewares to guard routes based on authentication and user roles - Add auth.client.ts plugin to boot-sync logged in user details - Declare custom PageMeta type definitions to support role-based authorization rules
This commit is contained in:
@@ -8,6 +8,55 @@ import type {
|
||||
} from "~/types/api";
|
||||
|
||||
export const useAuth = () => {
|
||||
const token = useCookie('auth_token', {
|
||||
maxAge: 60 * 60 * 12,
|
||||
sameSite: 'lax',
|
||||
watch: true
|
||||
})
|
||||
|
||||
const tokenState = useState<string | null>('auth_token_state', () => token.value ?? null)
|
||||
|
||||
type UserContext = CurrentUserResponse['user']
|
||||
const user = useState<UserContext | null>('auth_user', () => null)
|
||||
const isSyncingUser = useState<boolean>('auth_syncing', () => false)
|
||||
const isAuthenticated = computed(() => !!(tokenState.value || token.value))
|
||||
|
||||
watch(() => token.value, (newVal) => {
|
||||
tokenState.value = newVal || null
|
||||
})
|
||||
|
||||
const syncUser = async () => {
|
||||
const tokenVal = tokenState.value || token.value
|
||||
if (!tokenVal || isSyncingUser.value) return
|
||||
|
||||
isSyncingUser.value = true
|
||||
try {
|
||||
const res = await fetchCurrentUser()
|
||||
if (res.ok) {
|
||||
console.log('[Auth] User synced successfully')
|
||||
user.value = res.user
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[Auth] Sync failed, logging out:', error)
|
||||
logout()
|
||||
} finally {
|
||||
isSyncingUser.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoginSuccess = async (jwtToken: string) => {
|
||||
token.value = jwtToken
|
||||
tokenState.value = jwtToken
|
||||
await syncUser()
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
token.value = null
|
||||
tokenState.value = null
|
||||
user.value = null
|
||||
navigateTo('/auth/login')
|
||||
}
|
||||
|
||||
const register = (body: RegisterCitizenRequest) =>
|
||||
useApiFetch<RegisterCitizenResponse>('/api/v1/auth/register', { method: 'POST', body })
|
||||
|
||||
@@ -36,6 +85,15 @@ export const useAuth = () => {
|
||||
useApiFetch<OkResponse>(`/api/v1/notifications/${id}/read`, { method: 'PATCH' })
|
||||
|
||||
return {
|
||||
user,
|
||||
token,
|
||||
tokenState,
|
||||
isSyncingUser,
|
||||
isAuthenticated,
|
||||
handleLoginSuccess,
|
||||
syncUser,
|
||||
logout,
|
||||
|
||||
register,
|
||||
requestOtp,
|
||||
verifyOtp,
|
||||
|
||||
Reference in New Issue
Block a user