feat(admin): add IA shell and protected section skeleton routes
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
import { hasPermission } from "@cms/content/rbac"
|
||||
import { isAdminSelfRegistrationEnabled, setAdminSelfRegistrationEnabled } from "@cms/db"
|
||||
import { Button } from "@cms/ui/button"
|
||||
import { revalidatePath } from "next/cache"
|
||||
import Link from "next/link"
|
||||
import { redirect } from "next/navigation"
|
||||
|
||||
import { AdminLocaleSwitcher } from "@/components/admin-locale-switcher"
|
||||
import { AdminShell } from "@/components/admin-shell"
|
||||
import { translateMessage } from "@/i18n/messages"
|
||||
import { getAdminMessages, resolveAdminLocale } from "@/i18n/server"
|
||||
import { resolveRoleFromServerContext } from "@/lib/access-server"
|
||||
import { requirePermissionForRoute } from "@/lib/route-guards"
|
||||
|
||||
type SearchParamsInput = Promise<Record<string, string | string[] | undefined>>
|
||||
|
||||
@@ -21,15 +20,11 @@ function toSingleValue(input: string | string[] | undefined): string | null {
|
||||
}
|
||||
|
||||
async function requireSettingsPermission() {
|
||||
const role = await resolveRoleFromServerContext()
|
||||
|
||||
if (!role) {
|
||||
redirect("/login?next=/settings")
|
||||
}
|
||||
|
||||
if (!hasPermission(role, "users:manage_roles", "global")) {
|
||||
redirect("/unauthorized?required=users:manage_roles&scope=global")
|
||||
}
|
||||
await requirePermissionForRoute({
|
||||
nextPath: "/settings",
|
||||
permission: "users:manage_roles",
|
||||
scope: "global",
|
||||
})
|
||||
}
|
||||
|
||||
async function getSettingsTranslator() {
|
||||
@@ -85,7 +80,11 @@ async function updateRegistrationPolicyAction(formData: FormData) {
|
||||
}
|
||||
|
||||
export default async function SettingsPage({ searchParams }: { searchParams: SearchParamsInput }) {
|
||||
await requireSettingsPermission()
|
||||
const role = await requirePermissionForRoute({
|
||||
nextPath: "/settings",
|
||||
permission: "users:manage_roles",
|
||||
scope: "global",
|
||||
})
|
||||
|
||||
const [params, locale, isRegistrationEnabled] = await Promise.all([
|
||||
searchParams,
|
||||
@@ -99,31 +98,24 @@ export default async function SettingsPage({ searchParams }: { searchParams: Sea
|
||||
const error = toSingleValue(params.error)
|
||||
|
||||
return (
|
||||
<main className="mx-auto flex min-h-screen w-full max-w-4xl flex-col gap-8 px-6 py-16">
|
||||
<header className="space-y-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<p className="text-sm uppercase tracking-[0.2em] text-neutral-500">
|
||||
{t("settings.badge", "Admin Settings")}
|
||||
</p>
|
||||
<AdminLocaleSwitcher />
|
||||
</div>
|
||||
<h1 className="text-4xl font-semibold tracking-tight">{t("settings.title", "Settings")}</h1>
|
||||
<p className="text-neutral-600">
|
||||
{t(
|
||||
"settings.description",
|
||||
"Manage runtime policies for the admin authentication and onboarding flow.",
|
||||
)}
|
||||
</p>
|
||||
<div className="flex items-center gap-3 pt-2">
|
||||
<Link
|
||||
href="/"
|
||||
className="inline-flex rounded-md border border-neutral-300 px-4 py-2 text-sm font-medium hover:bg-neutral-100"
|
||||
>
|
||||
{t("settings.actions.backToDashboard", "Back to dashboard")}
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<AdminShell
|
||||
role={role}
|
||||
activePath="/settings"
|
||||
badge={t("settings.badge", "Admin Settings")}
|
||||
title={t("settings.title", "Settings")}
|
||||
description={t(
|
||||
"settings.description",
|
||||
"Manage runtime policies for the admin authentication and onboarding flow.",
|
||||
)}
|
||||
actions={
|
||||
<Link
|
||||
href="/"
|
||||
className="inline-flex rounded-md border border-neutral-300 px-4 py-2 text-sm font-medium hover:bg-neutral-100"
|
||||
>
|
||||
{t("settings.actions.backToDashboard", "Back to dashboard")}
|
||||
</Link>
|
||||
}
|
||||
>
|
||||
{notice ? (
|
||||
<section className="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
|
||||
{notice}
|
||||
@@ -183,6 +175,6 @@ export default async function SettingsPage({ searchParams }: { searchParams: Sea
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</AdminShell>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user