UNPKG

@eturino/claims

Version:

Claim, ClaimSet and Ability for permissions (Typescript port of https://github.com/eturino/claims)

88 lines (77 loc) 3.42 kB
import { type KeySet, all, some } from "@eturino/key-set"; import { type Claim, type IClaimData, extractVerbResource } from "./claim"; import { type ClaimSet, buildClaimSet } from "./claim-set"; export class Ability { constructor( public readonly permitted: ClaimSet, public readonly prohibited: ClaimSet, ) {} /** Returns a new ability with clones with the claim sets */ public clone(): Ability { return new Ability(this.permitted.clone(), this.prohibited.clone()); } /** * returns a string with the permitted and prohibited jsons inside, for caching purposes */ get cacheID(): string { return `(${this.permitted.toJSONString()},${this.prohibited.toJSONString()})`; } /** * inverse of `can()` * @param query can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` * * @see can */ public cannot(query: string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>): boolean { return !this.can(query); } /** * return true if permitted is true and prohibited is false * - permitted -> if the permitted ClaimSet returns true on `check()` for the given query * - prohibited -> if the prohibited ClaimSet returns true on `check()` for the given query * * @param query can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` * @see ClaimSet */ public can(query: string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>): boolean { const parsedQuery = extractVerbResource(query); return this.permitted.check(parsedQuery) && !this.prohibited.check(parsedQuery); } /** * returns true if there is a prohibited claim that returns true on `check()` * * @param query can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` * @see ClaimSet * @see Claim */ public isExplicitlyProhibited(query: string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>): boolean { return this.prohibited.check(query); } /** * returns a KeySet describing the access of this ability to the children of the given query: * allows on direct descendants, forbids on direct children * @param query can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` */ accessToResources(query: string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>): KeySet<string> { const allowed = this.permitted.check(query) ? all<string>() : some(this.permitted.directDescendants(query)); const forbidden = this.prohibited.check(query) ? all<string>() : some(this.prohibited.directChildren(query)); return allowed.remove(forbidden); } } /** * * @param permittedStrings each element can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` * @param prohibitedStrings each element can be a string ("verb:resource" or "verb:*") or an object with `verb` and `resource` * @see buildClaimSet * @see Ability */ export function buildAbility( permittedStrings: readonly (string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>)[], prohibitedStrings: readonly (string | IClaimData | Claim | Readonly<IClaimData> | Readonly<Claim>)[], ): Ability { const permitted = buildClaimSet(permittedStrings); const prohibited = buildClaimSet(prohibitedStrings); return new Ability(permitted, prohibited); }