import { PartialPermissionSet } from 'app/common/ACLPermissions'; import { CellValue, RowRecord } from 'app/common/DocActions'; export interface RuleSet { tableId: '*' | string; colIds: '*' | string[]; // The default permissions for this resource, if set, are represented by a RulePart with // aclFormula of "", which must be the last element of body. body: RulePart[]; } export interface RulePart { origRecord?: RowRecord; // Original record used to create this RulePart. aclFormula: string; permissions: PartialPermissionSet; permissionsText: string; // The text version of PermissionSet, as stored. // Compiled version of aclFormula. matchFunc?: AclMatchFunc; // Optional memo, currently extracted from comment in formula. memo?: string; } // Light wrapper for reading records or user attributes. export interface InfoView { get(key: string): CellValue; toJSON(): {[key: string]: any}; } // As InfoView, but also supporting writing. export interface InfoEditor { get(key: string): CellValue; set(key: string, val: CellValue): this; toJSON(): {[key: string]: any}; } // Represents user info, which may include properties which are themselves RowRecords. export type UserInfo = Record>; /** * Input into the AclMatchFunc. Compiled formulas evaluate AclMatchInput to produce a boolean. */ export interface AclMatchInput { user: UserInfo; rec?: InfoView; newRec?: InfoView; } /** * The actual boolean function that can evaluate a request. The result of compiling ParsedAclFormula. */ export type AclMatchFunc = (input: AclMatchInput) => boolean; /** * Representation of a parsed ACL formula. */ export type ParsedAclFormula = [string, ...Array]; /** * Observations about a formula. */ export interface FormulaProperties { hasRecOrNewRec?: boolean; } export interface UserAttributeRule { origRecord?: RowRecord; // Original record used to create this UserAttributeRule. name: string; // Should be unique among UserAttributeRules. tableId: string; // Table in which to look up an existing attribute. lookupColId: string; // Column in tableId in which to do the lookup. charId: string; // Attribute to look up, possibly a path. E.g. 'Email' or 'office.city'. } /** * Check some key facts about the formula. */ export function getFormulaProperties(formula: ParsedAclFormula) { const result: FormulaProperties = {} if (usesRec(formula)) { result.hasRecOrNewRec = true; } return result; } /** * Check whether a formula mentions `rec` or `newRec`. */ export function usesRec(formula: ParsedAclFormula): boolean { if (!Array.isArray(formula)) { throw new Error('expected a list'); } if (formula[0] === 'Name' && (formula[1] === 'rec' || formula[1] === 'newRec')) { return true; } return formula.some(el => { if (!Array.isArray(el)) { return false; } return usesRec(el as any); }); }