UNPKG

@clickup/ent-framework

Version:

A PostgreSQL graph-database-alike library with microsharding and row-level security

51 lines 2.64 kB
import type { VC } from "../VC"; import type { Rule, RuleResult } from "./Rule"; /** * This is a hearth of permissions checking, a machine which evaluates the rules * chain from top to bottom (one after another) and makes the decision based on * the following logic: * - ALLOW immediately allows the chain, the rest of the rules are not checked. * It's an eager allowance. * - DENY immediately denies the chain, the rest of the rules are not checked. * It's an eager denial. * - TOLERATE delegates the decision to the next rules; if it's the last * decision in the chain, then allows the chain. I.e. it's like an allowance, * but only if everyone else is tolerant. * - SKIP also delegates the decision to the next rules, but if it's the last * rule in the chain (i.e. nothing to skip to anymore), denies the chain. I.e. * it's "I don't vote here, please ask others". * - An empty chain is always denied. * * Having TOLERATE decision may sound superfluous, but unfortunately it's not. * The TOLERATE enables usage of the same machinery for both read-like checks * (where we typically want ANY of the rules to be okay with the row) and for * write-like checks (where we typically want ALL rules to be okay with the * row). Having the same logic for everything simplifies the code. * * If parallel argument is true, all the rules are run at once in concurrent * promises before the machine starts. This doesn't affect the final result, * just speeds up processing if we know that there is a high chance that most of * the rules will likely return TOLERATE and we'll anyway need to evaluate all * of them (e.g. most of the rules are Require, like in write operations). As * opposed, for read operation, there is a high chance for the first rule (which * is often AllowIf) to succeed, so we evaluate the rules sequentially, not in * parallel (to minimize the number of DB queries). * * Example of a chain (the order of rules always matters!): * - new Require(new OutgoingEdgePointsToVC("user_id")) * - new Require(new CanReadOutgoingEdge("post_id", EntPost)) * * Example of a chain: * - new AllowIf(new OutgoingEdgePointsToVC("user_id")) * - new AllowIf(new CanReadOutgoingEdge("post_id", EntPost)) * * Example of a chain: * - new DenyIf(new UserIsPendingApproval()) * - new AllowIf(new OutgoingEdgePointsToVC("user_id")) */ export declare function evaluate<TInput extends object>(vc: VC, input: TInput, rules: Array<Rule<TInput>>, fashion: "parallel" | "sequential"): Promise<{ allow: boolean; results: RuleResult[]; cause: string; }>; //# sourceMappingURL=evaluate.d.ts.map