2035f73e7d
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import type { SystemRole } from "@/shared/schemas/common";
|
||
|
||
export type AdminAction =
|
||
| { type: "delete" }
|
||
| { type: "ban" }
|
||
| { type: "setRole"; role: SystemRole }
|
||
| { type: "edit" }
|
||
| { type: "setPassword" };
|
||
|
||
export type GuardContext = {
|
||
actorId: string;
|
||
target: { id: string; role: SystemRole };
|
||
/** Sistemdeki toplam admin sayısı (hedef dahil). */
|
||
adminCount: number;
|
||
};
|
||
|
||
export type GuardViolation = "self" | "lastAdmin";
|
||
|
||
/**
|
||
* Admin işlem kuralları (arayüz ve sunucu aynı fonksiyonu kullanır):
|
||
* - Admin kendini silemez, askıya alamaz ve kendi admin rolünü kaldıramaz.
|
||
* - Sistemdeki son admin silinemez, askıya alınamaz veya rolü düşürülemez.
|
||
*/
|
||
export function checkAdminAction(action: AdminAction, ctx: GuardContext): GuardViolation | null {
|
||
const isSelf = ctx.actorId === ctx.target.id;
|
||
const removesAdmin =
|
||
ctx.target.role === "admin" &&
|
||
(action.type === "delete" ||
|
||
action.type === "ban" ||
|
||
(action.type === "setRole" && action.role !== "admin"));
|
||
|
||
if (isSelf && (action.type === "delete" || action.type === "ban" || removesAdmin)) {
|
||
return "self";
|
||
}
|
||
if (removesAdmin && ctx.adminCount <= 1) return "lastAdmin";
|
||
return null;
|
||
}
|