fix(admin): P0 integrity — permanent bans, ACL sidebar, rank guards
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
11004626c7
commit
75cdfdebe4
14 files changed
+458
-68
No files matched your search
@@ -2,6 +2,7 @@ import { redirect } from "next/navigation";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { createBan, liftBan } from "@/actions/admin-bans";
|
||||
import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { activeBanWhere, unixNow } from "@/lib/bans";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
@@ -18,11 +19,11 @@ export default async function AdminBans() {
|
||||
}
|
||||
|
||||
const t = await getTranslations("pages.admin.bans");
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const now = unixNow();
|
||||
let bans: Awaited<ReturnType<typeof prisma.ban.findMany>> = [];
|
||||
try {
|
||||
bans = await prisma.ban.findMany({
|
||||
where: { banExpire: { gt: now } },
|
||||
where: activeBanWhere(now),
|
||||
orderBy: { timestamp: "desc" },
|
||||
take: 100,
|
||||
});
|
||||
@@ -30,7 +31,6 @@ export default async function AdminBans() {
|
||||
bans = [];
|
||||
}
|
||||
|
||||
// banExpire of 0 means permanent in the emulator schema.
|
||||
const permanent = bans.filter((b) => b.banExpire === 0).length;
|
||||
const accountBans = bans.filter((b) => b.type === "account").length;
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ import { AdminTopbar } from "@/components/admin/admin-topbar";
|
||||
import { LanguageSwitcher } from "@/components/language-switcher";
|
||||
import { ThemeSwitcher } from "@/components/theme-switcher";
|
||||
import { requireStaff } from "@/lib/admin/guard";
|
||||
import { collectNavPermissionSlugs } from "@/lib/admin-nav";
|
||||
import { setCsrfCookie } from "@/lib/foundation/security";
|
||||
import { canAccess, getAdminContext } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
@@ -66,6 +68,13 @@ async function Sidebar({
|
||||
}) {
|
||||
const t = await getTranslations("pages.admin.nav");
|
||||
const initial = staff.username.charAt(0).toUpperCase();
|
||||
const { permissions } = await getAdminContext();
|
||||
const isSuperAdmin = permissions.isSuperAdmin;
|
||||
const allowedPermissions = isSuperAdmin
|
||||
? []
|
||||
: collectNavPermissionSlugs().filter((slug) =>
|
||||
canAccess(permissions, slug, staff.rank),
|
||||
);
|
||||
|
||||
return (
|
||||
<aside
|
||||
@@ -93,7 +102,10 @@ async function Sidebar({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AdminSidebarNav />
|
||||
<AdminSidebarNav
|
||||
allowedPermissions={allowedPermissions}
|
||||
isSuperAdmin={isSuperAdmin}
|
||||
/>
|
||||
|
||||
<div className="shrink-0 border-t border-[var(--admin-border)] px-3 py-3">
|
||||
<Link
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import Link from "next/link";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { activeBanWhere } from "@/lib/bans";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -31,7 +32,7 @@ export default async function AdminDashboard() {
|
||||
prisma.user.count({ where: { online: "1" } }),
|
||||
prisma.websiteArticles.count(),
|
||||
prisma.ban.count({
|
||||
where: { banExpire: { gt: Math.floor(Date.now() / 1000) } },
|
||||
where: activeBanWhere(),
|
||||
}),
|
||||
]);
|
||||
} catch {}
|
||||
|
||||
Reference in new issue
Block a user