fix(admin): P0 integrity — permanent bans, ACL sidebar, rank guards
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m36s

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-22 19:01:59 +02:00
1 parent 11004626c7
commit 75cdfdebe4
14 files changed
+458 -68

No files matched your search

+29 -3
View File
@@ -5,7 +5,11 @@ import { usePathname } from "next/navigation";
import { useTranslations } from "next-intl";
import { useCallback, useEffect, useMemo, useState } from "react";
import { AdminNavLink } from "@/components/admin/admin-nav-link";
import { ADMIN_NAV_GROUPS, type AdminNavItem } from "@/lib/admin-nav";
import {
ADMIN_NAV_GROUPS,
type AdminNavItem,
navItemIsAllowed,
} from "@/lib/admin-nav";
import { cn } from "@/lib/utils";
const STORAGE_KEY = "admin-nav-collapsed";
@@ -52,13 +56,35 @@ function persistCollapsed(next: Record<string, boolean>) {
}
}
export function AdminSidebarNav() {
export function AdminSidebarNav({
allowedPermissions = [],
isSuperAdmin = false,
}: {
/** ACL slugs the staff member holds (ignored when isSuperAdmin). */
allowedPermissions?: string[];
isSuperAdmin?: boolean;
}) {
const t = useTranslations("pages.admin.nav");
const pathname = usePathname() ?? "";
const [collapsed, setCollapsed] = useState<Record<string, boolean>>({});
const [hydrated, setHydrated] = useState(false);
const groups = useMemo(() => ADMIN_NAV_GROUPS, []);
const allowed = useMemo(
() => new Set(allowedPermissions),
[allowedPermissions],
);
const groups = useMemo(() => {
const access = {
isSuperAdmin,
has: (slug: string) => allowed.has(slug),
};
return ADMIN_NAV_GROUPS.map((group) => ({
...group,
items: group.items.filter((item) => navItemIsAllowed(item, access)),
})).filter((group) => group.items.length > 0);
}, [allowed, isSuperAdmin]);
const allKeys = useMemo(() => groups.map((g) => g.labelKey), [groups]);
useEffect(() => {