import { BadRequestException, ForbiddenException } from "@nestjs/common"; import { rolesRepo } from "@eden/database"; import { SUPER_ADMIN_ROLE } from "./permissions.js"; /** * Role weight (eden.md §1.6, ADR-0004): an actor can never assign a role * heavier than their own, nor act on a user whose *current* role is * heavier than the actor's — orthogonal to the resource/action/scope * permission check. super_admin (weight 100, hardcoded ceiling) always * passes the *weight comparison* — but role existence is still validated * even for super_admin, otherwise an invalid role key would sail past * this check and only fail later as an unhandled FK-constraint 500 from * the database (an earlier bug caught by manual testing: this function * must be the single place that turns "role doesn't exist" into a clean * 400, not the DB constraint). */ async function getWeight(roleKey: string): Promise { const role = await rolesRepo.getRoleByKey(roleKey); if (!role) throw new BadRequestException(`Papel '${roleKey}' não existe`); return role.weight; } export async function assertCanAssignRole(actorRoleKey: string, targetRoleKey: string): Promise { const targetWeight = await getWeight(targetRoleKey); if (actorRoleKey === SUPER_ADMIN_ROLE) return; const actorWeight = await getWeight(actorRoleKey); if (targetWeight > actorWeight) { throw new ForbiddenException("Você não pode atribuir um papel com peso maior que o seu."); } } export async function assertCanActOnUser( actorRoleKey: string, targetUserRoleKey: string, ): Promise { const targetWeight = await getWeight(targetUserRoleKey); if (actorRoleKey === SUPER_ADMIN_ROLE) return; const actorWeight = await getWeight(actorRoleKey); if (targetWeight > actorWeight) { throw new ForbiddenException("Você não pode alterar um usuário com papel de peso maior que o seu."); } }