kereru-forms/frontend/src/auth/gates.tsx

50 lines
1.5 KiB
TypeScript

import type { ReactNode } from 'react'
import { Link, Navigate, useLocation } from 'react-router-dom'
import { useAuth } from './AuthContext'
import type { AuthUser } from '../lib/types'
type RequiredRole = 'admin' | 'view' | 'management'
export function ManagementGate({
children,
role = 'management',
}: {
children: ReactNode
role?: RequiredRole
}) {
const { loading, user } = useAuth()
const location = useLocation()
if (loading) {
return <p className="text-slate-500 dark:text-slate-400">Checking sign-in…</p>
}
if (!user) {
return <Navigate to="/login" replace state={{ from: location.pathname + location.search }} />
}
if (!hasRole(user, role)) {
return <AccessDenied role={role} />
}
return <>{children}</>
}
function hasRole(user: AuthUser, role: RequiredRole): boolean {
if (role === 'admin') return user.canAdmin
if (role === 'view') return user.canView
return user.canAdmin || user.canView
}
function AccessDenied({ role }: { role: RequiredRole }) {
const roleName = role === 'management' ? 'management' : `${role} role`
return (
<div className="card mx-auto max-w-xl space-y-3 text-center">
<h1 className="text-xl font-bold">Access denied</h1>
<p className="text-slate-500 dark:text-slate-400">
Your account does not have the {roleName} permission required for this page.
</p>
<Link to="/" className="btn-primary mx-auto w-fit">
Back to forms
</Link>
</div>
)
}