Add PostgreSQL and Redis integration for users and sessions Implement password and WebAuthn passkey login flows Add Docker stack, super-admin seeding, and protected routes
79 lines
1.7 KiB
TypeScript
79 lines
1.7 KiB
TypeScript
import type { H3Event } from 'h3'
|
|
|
|
import type { UserRole } from '~~/shared/auth'
|
|
|
|
import { createUserSession, destroyUserSession, getUserSession } from './session'
|
|
import { getUserById, updateLastLogin, type UserAuthRecord } from './user-repository'
|
|
|
|
export function normalizeUsername(value: string) {
|
|
return value.trim().toLowerCase()
|
|
}
|
|
|
|
export async function getAuthContext(event: H3Event): Promise<{
|
|
session: Awaited<ReturnType<typeof getUserSession>>
|
|
user: UserAuthRecord
|
|
} | null> {
|
|
const session = await getUserSession(event)
|
|
|
|
if (!session) {
|
|
return null
|
|
}
|
|
|
|
const user = await getUserById(session.userId)
|
|
|
|
if (!user || !user.isActive) {
|
|
await destroyUserSession(event)
|
|
return null
|
|
}
|
|
|
|
return {
|
|
session,
|
|
user
|
|
}
|
|
}
|
|
|
|
export async function requireAuth(event: H3Event) {
|
|
const auth = await getAuthContext(event)
|
|
|
|
if (!auth) {
|
|
throw createError({
|
|
statusCode: 401,
|
|
statusMessage: 'Authentication required'
|
|
})
|
|
}
|
|
|
|
return auth
|
|
}
|
|
|
|
export async function requireRole(event: H3Event, role: UserRole) {
|
|
const auth = await requireAuth(event)
|
|
|
|
if (auth.user.role !== role) {
|
|
throw createError({
|
|
statusCode: 403,
|
|
statusMessage: 'You are not allowed to perform this action'
|
|
})
|
|
}
|
|
|
|
return auth
|
|
}
|
|
|
|
export async function signInUser(event: H3Event, user: UserAuthRecord, remember: boolean) {
|
|
await createUserSession(event, {
|
|
userId: user.id,
|
|
remember
|
|
})
|
|
await updateLastLogin(user.id)
|
|
|
|
const refreshedUser = await getUserById(user.id)
|
|
|
|
if (!refreshedUser) {
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Unable to load authenticated user'
|
|
})
|
|
}
|
|
|
|
return refreshedUser
|
|
}
|