Secure API endpoints with requireBookingManager authorization check Update confirmation page to prompt for login if unauthorized Add safe redirect handling to login and guest middleware
89 lines
2.0 KiB
TypeScript
89 lines
2.0 KiB
TypeScript
import type { H3Event } from 'h3'
|
|
import type { PublicBooking } from '~~/shared/booking'
|
|
|
|
import { normalizeUsername, type UserRole } from '~~/shared/auth'
|
|
|
|
import { createUserSession, destroyUserSession, getUserSession } from './session'
|
|
import { getUserById, updateLastLogin, type UserAuthRecord } from './user-repository'
|
|
|
|
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 requireBookingManager(event: H3Event, booking: Pick<PublicBooking, 'personInChargeId'>) {
|
|
const auth = await requireAuth(event)
|
|
|
|
if (auth.user.role !== 'super_admin' && auth.user.id !== booking.personInChargeId) {
|
|
throw createError({
|
|
statusCode: 403,
|
|
statusMessage: 'You are not allowed to manage this booking'
|
|
})
|
|
}
|
|
|
|
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
|
|
}
|