revert fb8e77bb68
Local Build and Deploy / deploy (push) Successful in 1m11s
Local Build and Deploy / deploy (push) Successful in 1m11s
revert style: clean up code with prettier and eslint
This commit is contained in:
1 parent
27de078f54
commit
e85e4d74ea
378 files changed
+20710
-22428
No files matched your search
+70
-91
@@ -1,23 +1,23 @@
|
||||
import { unstable_cache } from "next/cache";
|
||||
import { redirect } from "next/navigation";
|
||||
import { cache } from "react";
|
||||
import { auth } from "./auth";
|
||||
import { sessionUserId } from "./auth/session-user";
|
||||
import { prisma } from "./prisma";
|
||||
import { logAuthorizationEvent } from "./admin/authorization-events";
|
||||
import { isDynamicSuperAdmin } from "./admin/authorization-policy";
|
||||
import { resolveAuthorizationState } from "./admin/rank-authority";
|
||||
import { unstable_cache } from 'next/cache'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { cache } from 'react'
|
||||
import { auth } from './auth'
|
||||
import { sessionUserId } from './auth/session-user'
|
||||
import { prisma } from './prisma'
|
||||
import { logAuthorizationEvent } from './admin/authorization-events'
|
||||
import { isDynamicSuperAdmin } from './admin/authorization-policy'
|
||||
import { resolveAuthorizationState } from './admin/rank-authority'
|
||||
|
||||
// Re-export PERMS from the standalone file (safe for client components)
|
||||
export { PERMS } from "./permission-slugs";
|
||||
export { PERMS } from './permission-slugs'
|
||||
|
||||
import { PERMS } from "./permission-slugs";
|
||||
import { PERMS } from './permission-slugs'
|
||||
|
||||
// ── Permission Set ──────────────────────────────────────────────────
|
||||
|
||||
export type { PermissionSet } from "@/types/admin";
|
||||
export type { PermissionSet } from '@/types/admin'
|
||||
|
||||
import type { PermissionSet } from "@/types/admin";
|
||||
import type { PermissionSet } from '@/types/admin'
|
||||
|
||||
function createEmptySet(): PermissionSet {
|
||||
return {
|
||||
@@ -25,7 +25,7 @@ function createEmptySet(): PermissionSet {
|
||||
hasAny: () => false,
|
||||
hasAll: () => false,
|
||||
isSuperAdmin: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,12 +48,12 @@ const getCachedPermissionSlugs = unstable_cache(
|
||||
FROM acl_roles ar
|
||||
WHERE ar.slug = ${`rank_${rank}`}
|
||||
)
|
||||
`;
|
||||
return rows.map((r) => r.slug);
|
||||
`
|
||||
return rows.map((r) => r.slug)
|
||||
},
|
||||
["user-permissions"],
|
||||
{ revalidate: 60, tags: ["permissions"] },
|
||||
);
|
||||
['user-permissions'],
|
||||
{ revalidate: 60, tags: ['permissions'] },
|
||||
)
|
||||
|
||||
/**
|
||||
* Load permission slugs for a database-refreshed user rank. The dynamically
|
||||
@@ -73,32 +73,25 @@ export const loadUserPermissions = cache(async function loadUserPermissions(
|
||||
hasAny: () => true,
|
||||
hasAll: () => true,
|
||||
isSuperAdmin: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const slugArray = await getCachedPermissionSlugs(userId, rank);
|
||||
if (slugArray.length === 0) return createEmptySet();
|
||||
const slugArray = await getCachedPermissionSlugs(userId, rank)
|
||||
if (slugArray.length === 0) return createEmptySet()
|
||||
|
||||
const slugs = new Set(slugArray);
|
||||
const slugs = new Set(slugArray)
|
||||
return {
|
||||
has: (perm: string) => slugs.has(perm),
|
||||
hasAny: (...perms: string[]) => perms.some((p) => slugs.has(p)),
|
||||
hasAll: (...perms: string[]) => perms.every((p) => slugs.has(p)),
|
||||
isSuperAdmin: false,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
await logAuthorizationEvent({
|
||||
kind: "permission.load_error",
|
||||
userId,
|
||||
rank,
|
||||
source: "loadUserPermissions",
|
||||
reason: "ACL query failed",
|
||||
error,
|
||||
});
|
||||
await logAuthorizationEvent({ kind: 'permission.load_error', userId, rank, source: 'loadUserPermissions', reason: 'ACL query failed', error })
|
||||
// Fail-closed: return empty set on any error
|
||||
return createEmptySet();
|
||||
return createEmptySet()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
const getCurrentAuthorizationState = cache(async (userId: number) =>
|
||||
resolveAuthorizationState(userId, {
|
||||
@@ -106,11 +99,11 @@ const getCurrentAuthorizationState = cache(async (userId: number) =>
|
||||
highestRank: async () => {
|
||||
const rows = await prisma.$queryRaw<{ highest_rank: number | bigint | null }[]>`
|
||||
SELECT MAX(id) AS highest_rank FROM permission_ranks
|
||||
`;
|
||||
return rows[0]?.highest_rank == null ? null : Number(rows[0].highest_rank);
|
||||
`
|
||||
return rows[0]?.highest_rank == null ? null : Number(rows[0].highest_rank)
|
||||
},
|
||||
}),
|
||||
);
|
||||
)
|
||||
|
||||
// ── Context Helpers ─────────────────────────────────────────────────
|
||||
|
||||
@@ -119,23 +112,17 @@ const getCurrentAuthorizationState = cache(async (userId: number) =>
|
||||
* Redirects to login if not authenticated.
|
||||
*/
|
||||
export async function getAdminContext() {
|
||||
const session = await auth();
|
||||
const session = await auth()
|
||||
if (!session?.user) {
|
||||
redirect("/login");
|
||||
redirect('/login')
|
||||
}
|
||||
|
||||
const userId = sessionUserId(session.user.id);
|
||||
if (!userId) redirect("/login");
|
||||
const state = await getCurrentAuthorizationState(userId);
|
||||
if (!state) redirect("/login");
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank);
|
||||
return {
|
||||
session: {
|
||||
...session,
|
||||
user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank },
|
||||
},
|
||||
permissions,
|
||||
};
|
||||
const userId = sessionUserId(session.user.id)
|
||||
if (!userId) redirect('/login')
|
||||
const state = await getCurrentAuthorizationState(userId)
|
||||
if (!state) redirect('/login')
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank)
|
||||
return { session: { ...session, user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank } }, permissions }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,21 +130,15 @@ export async function getAdminContext() {
|
||||
* Returns null if not authenticated (caller handles 401).
|
||||
*/
|
||||
export async function getApiAdminContext() {
|
||||
const session = await auth();
|
||||
if (!session?.user) return null;
|
||||
const session = await auth()
|
||||
if (!session?.user) return null
|
||||
|
||||
const userId = sessionUserId(session.user.id);
|
||||
if (!userId) return null;
|
||||
const state = await getCurrentAuthorizationState(userId);
|
||||
if (!state) return null;
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank);
|
||||
return {
|
||||
session: {
|
||||
...session,
|
||||
user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank },
|
||||
},
|
||||
permissions,
|
||||
};
|
||||
const userId = sessionUserId(session.user.id)
|
||||
if (!userId) return null
|
||||
const state = await getCurrentAuthorizationState(userId)
|
||||
if (!state) return null
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank)
|
||||
return { session: { ...session, user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank } }, permissions }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +146,7 @@ export async function getApiAdminContext() {
|
||||
* All fallbacks are represented as ACL role permissions by migration 0011.
|
||||
*/
|
||||
export function canAccess(permissions: PermissionSet, slug: string, _rank?: number): boolean {
|
||||
return permissions.has(slug);
|
||||
return permissions.has(slug)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,34 +154,32 @@ export function canAccess(permissions: PermissionSet, slug: string, _rank?: numb
|
||||
* Redirects to login if unauthenticated and to / without moderator ACL access.
|
||||
*/
|
||||
export async function getModContext() {
|
||||
const session = await auth();
|
||||
const session = await auth()
|
||||
if (!session?.user) {
|
||||
redirect("/login");
|
||||
redirect('/login')
|
||||
}
|
||||
|
||||
const userId = sessionUserId(session.user.id);
|
||||
if (!userId) redirect("/login");
|
||||
const state = await getCurrentAuthorizationState(userId);
|
||||
if (!state) redirect("/");
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank);
|
||||
if (!canAccess(permissions, PERMS.MOD_DASHBOARD)) redirect("/");
|
||||
return {
|
||||
session: {
|
||||
...session,
|
||||
user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank },
|
||||
},
|
||||
permissions,
|
||||
};
|
||||
const userId = sessionUserId(session.user.id)
|
||||
if (!userId) redirect('/login')
|
||||
const state = await getCurrentAuthorizationState(userId)
|
||||
if (!state) redirect('/')
|
||||
const permissions = await loadUserPermissions(userId, state.actor.rank, state.highestRank)
|
||||
if (!canAccess(permissions, PERMS.MOD_DASHBOARD)) redirect('/')
|
||||
return { session: { ...session, user: { ...session.user, id: userId, username: state.actor.username, rank: state.actor.rank } }, permissions }
|
||||
}
|
||||
|
||||
// ── Legacy single-check functions (kept for backward compatibility) ──
|
||||
|
||||
/** Check if a user has a CMS permission using their current database rank. */
|
||||
export async function checkPermission(userId: number, _rank: number, permission: string): Promise<boolean> {
|
||||
const state = await getCurrentAuthorizationState(userId);
|
||||
if (!state) return false;
|
||||
const perms = await loadUserPermissions(userId, state.actor.rank, state.highestRank);
|
||||
return perms.has(permission);
|
||||
export async function checkPermission(
|
||||
userId: number,
|
||||
_rank: number,
|
||||
permission: string,
|
||||
): Promise<boolean> {
|
||||
const state = await getCurrentAuthorizationState(userId)
|
||||
if (!state) return false
|
||||
const perms = await loadUserPermissions(userId, state.actor.rank, state.highestRank)
|
||||
return perms.has(permission)
|
||||
}
|
||||
|
||||
/** Check multiple permissions (user needs ALL of them) */
|
||||
@@ -209,13 +188,13 @@ export async function checkAllPermissions(
|
||||
_rank: number,
|
||||
permissions: string[],
|
||||
): Promise<boolean> {
|
||||
const state = await getCurrentAuthorizationState(userId);
|
||||
if (!state) return false;
|
||||
const perms = await loadUserPermissions(userId, state.actor.rank, state.highestRank);
|
||||
return perms.hasAll(...permissions);
|
||||
const state = await getCurrentAuthorizationState(userId)
|
||||
if (!state) return false
|
||||
const perms = await loadUserPermissions(userId, state.actor.rank, state.highestRank)
|
||||
return perms.hasAll(...permissions)
|
||||
}
|
||||
|
||||
/** Check if user has admin access */
|
||||
export async function hasAdminAccess(userId: number, rank: number): Promise<boolean> {
|
||||
return checkPermission(userId, rank, PERMS.ADMIN_DASHBOARD);
|
||||
return checkPermission(userId, rank, PERMS.ADMIN_DASHBOARD)
|
||||
}
|
||||
Reference in new issue
Block a user