46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
import type { AdminPermissionName } from "@hivegrid/db/admin-permissions";
|
|
import { adminHasPermission } from "@hivegrid/db/admin-rbac.server";
|
|
import { runWithRlsContext } from "@hivegrid/db/rls-context.server";
|
|
|
|
import { NOT_FOUND_ENVELOPE } from "~/utils/errors.server";
|
|
import { getUserInfo, getValidatedServerSession } from "~/utils/session.server";
|
|
|
|
export type AdminPermissionRequirement =
|
|
| AdminPermissionName
|
|
| readonly AdminPermissionName[];
|
|
|
|
export async function requireAdminIdentityPermission(
|
|
request: Request,
|
|
permission: AdminPermissionRequirement
|
|
) {
|
|
const userInfo = await getUserInfo(request);
|
|
if (!userInfo.userId) throw Response.json(NOT_FOUND_ENVELOPE, { status: 404 });
|
|
const session = await getValidatedServerSession(request, userInfo);
|
|
if (!session || !("adminUser" in session) || session.adminUserId !== userInfo.userId) {
|
|
throw Response.json(NOT_FOUND_ENVELOPE, { status: 404 });
|
|
}
|
|
const permissions = Array.isArray(permission) ? permission : [permission];
|
|
const allowed = await runWithRlsContext(
|
|
{ userId: session.adminUserId },
|
|
async () =>
|
|
(
|
|
await Promise.all(
|
|
permissions.map((candidate) =>
|
|
adminHasPermission(session.adminUserId, candidate)
|
|
)
|
|
)
|
|
).some(Boolean)
|
|
);
|
|
if (!allowed) throw Response.json(NOT_FOUND_ENVELOPE, { status: 404 });
|
|
return session;
|
|
}
|
|
|
|
export async function runAsAdminIdentity<T>(
|
|
request: Request,
|
|
permission: AdminPermissionRequirement,
|
|
operation: (session: Awaited<ReturnType<typeof requireAdminIdentityPermission>>) => Promise<T>
|
|
): Promise<T> {
|
|
const session = await requireAdminIdentityPermission(request, permission);
|
|
return runWithRlsContext({ userId: session.adminUserId }, () => operation(session));
|
|
}
|