import { Log } from '@spinajs/log'; import { AccessControl, User } from '@spinajs/rbac'; import { AccountDisableAction, IRoleGuardConfig, RoleGuard } from '../interfaces.js'; /** A resolved grant map: resource -> action -> attribute list. */ type GrantMap = { [resource: string]: { [action: string]: string[]; }; }; /** * The shipped {@link RoleGuard}. * * Every check reads its switch from `rbac.admin.roleGuard`, so an application * turns one off in configuration instead of replacing the whole service — and * an application that needs a different rule entirely registers its own class * under {@link RoleGuard} and names it in `rbac.admin.roleGuard.service`. */ export declare class DefaultRoleGuard extends RoleGuard { protected Log: Log; protected Options: IRoleGuardConfig; protected SystemRole: string; /** * Declared roles, which is NOT the same set as the roles accesscontrol knows * about: a role may be declared for assignment and carry no grants yet. */ protected DeclaredRoles: Array<{ Name: string; }>; /** * Resolved late, never cached in a field: the container entry is replaced * whenever the rbac bootstrapper runs ( every test case does ), and a guard * holding the stale instance would answer from grants nobody configured. */ protected get AC(): AccessControl; assertCanAssignRoles(actor: User, target: User | null, roles: string[]): Promise; assertCanRevokeRole(actor: User, target: User, role: string): Promise; assertCanDisableAccount(actor: User, target: User, action: AccountDisableAction): Promise; assignableRoles(actor: User): string[]; /** * A missing actor is a programming error on a route that must be behind * `AuthorizedPolicy` — refused rather than waved through, because every * escalation check below is meaningless without one. */ protected assertActor(actor: User): void; protected assertKnownRole(role: string): void; protected assertNotSystemRole(role: string, verb: string): void; protected isSelf(actor: User, target: User): boolean; /** * Throws when `target` is the last account that can still act with `role`. * * Counts accounts that could actually log in — inactive and soft-deleted rows * are not a way back into the installation. */ protected assertNotLastHolder(role: string, action: string): Promise; /** * Active accounts holding `role`. * * Counted in the database. This used to narrow with LIKE and finish the job in * memory, because `withRole` compiled to `FIND_IN_SET` — MySQL only — and threw * a driver error on SQLite, turning "is this the last administrator" into a 500 * on every deployment that is not MySQL. Set membership is a per-dialect * statement now, so the scope answers everywhere and the workaround is gone. */ protected countActiveHolders(role: string): Promise; protected isPrivileged(role: string): boolean; protected rolesWithGrants(): string[]; protected allGrants(): GrantMap; /** Grants of one role, with its `$extend` chain resolved. */ protected grantsOfRole(role: string): GrantMap; /** * The caller's ceiling: the union of every role they hold. * * Deliberately the union and not the session's active role — an administrator * who can switch to a stronger role could otherwise be blocked from an * operation they can perform by switching first, which teaches people to * switch rather than to stay in the weaker role. */ protected grantsOf(actor: User): GrantMap; /** * True when `holder` permits everything `wanted` does. * * Attributes are compared as sets, with `*` covering anything. Negated * attributes ( `!Password` ) are treated as ordinary members: a holder that * lists the same negation still covers, one that does not is reported as not * covering. That errs towards refusing an assignment, which is the safe * direction for a guard. * * `:any` covers the matching `:own`, exactly as accesscontrol resolves them at * enforcement time. Without that an administrator holding `read:any` on users * would be told they cannot hand out a role holding `read:own` — a role * strictly weaker than their own. */ protected covers(holder: GrantMap, wanted: GrantMap): boolean; } export {}; //# sourceMappingURL=RoleGuard.d.ts.map