55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
"use client"
|
|
|
|
import Link from "next/link"
|
|
import { useAuthStore } from "@/lib/api/auth-store"
|
|
import { useAuthReady } from "@/lib/api/use-auth-ready"
|
|
import { useCurrentUser } from "@/lib/api/hooks/use-current-user"
|
|
import { adminScopesFromToken, isPlatformAdminFromToken } from "@/lib/auth/admin"
|
|
import { Button } from "@/components/ui/button"
|
|
|
|
export function AdminAccessGuard({ children }: { children: React.ReactNode }) {
|
|
const { ready, authenticated } = useAuthReady()
|
|
const token = useAuthStore((s) => s.accessToken)
|
|
const { data: me, isFetching: meLoading } = useCurrentUser()
|
|
|
|
if (!ready) {
|
|
return (
|
|
<p className="text-sm text-muted-foreground">Chargement de la session…</p>
|
|
)
|
|
}
|
|
|
|
if (!authenticated) {
|
|
return (
|
|
<div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 dark:border-amber-900/40 dark:bg-amber-950/30 dark:text-amber-200">
|
|
<p>Connectez-vous avec un compte administrateur pour accéder à cette interface.</p>
|
|
<Button asChild variant="outline" size="sm" className="mt-3">
|
|
<Link href="/login">Se connecter</Link>
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (meLoading && !me) {
|
|
return (
|
|
<p className="text-sm text-muted-foreground">Vérification des droits administrateur…</p>
|
|
)
|
|
}
|
|
|
|
const scopes = adminScopesFromToken(token)
|
|
const isAdmin =
|
|
isPlatformAdminFromToken(token) || scopes.read || me?.platform_admin === true
|
|
|
|
if (!isAdmin) {
|
|
return (
|
|
<div className="rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm text-destructive">
|
|
<p>Accès refusé. Votre compte ne dispose pas des droits d'administration.</p>
|
|
<Button asChild variant="outline" size="sm" className="mt-3">
|
|
<Link href="/mail">Retour à Ultimail</Link>
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return <>{children}</>
|
|
}
|