@casl/ability
Advanced tools
+283
-0
@@ -5,2 +5,285 @@ # Change Log | ||
| # [5.1.0](https://github.com/stalniy/casl/compare/@casl/ability@5.0.0...@casl/ability@5.1.0) (2020-12-26) | ||
| ### Bug Fixes | ||
| * **ability:** ensure default field matcher can match fields with partial patterns inside ([362f49f](https://github.com/stalniy/casl/commit/362f49fce07ceb08725f129ee4c7251d20fee9f2)), closes [#388](https://github.com/stalniy/casl/issues/388) | ||
| * **ability:** replaces getters with functions to ensure terser properly minifies them ([386ecb6](https://github.com/stalniy/casl/commit/386ecb6df79aa466f10e3e2eccea4d3771c97ad4)) | ||
| * **angular:** fixes sourcemap generation for the code built by ngc ([7715263](https://github.com/stalniy/casl/commit/771526379ff8203170a433d71b68644a48ff44eb)), closes [#387](https://github.com/stalniy/casl/issues/387) [#382](https://github.com/stalniy/casl/issues/382) | ||
| * **build:** ensure dist is updated before ([0a879f7](https://github.com/stalniy/casl/commit/0a879f7162b8e5010a78ddff0f858f00b3537aa5)) | ||
| * **conditions:** moves logic related to compare complex types to @ucast/mongo2js ([9bd6a1b](https://github.com/stalniy/casl/commit/9bd6a1b90f6f949e8b6eb51cc406f6c44f33a705)) | ||
| * **condtions:** adds interpreter for `$and` parsing instruction ([3166a32](https://github.com/stalniy/casl/commit/3166a32a4803b06ceb7a682007b503b2185a7240)) | ||
| * **extra:** makes `permittedFieldsOf` to iterate from the end of array ([81e6409](https://github.com/stalniy/casl/commit/81e64096eb780762e117dae05cfa7cafad801aa3)) | ||
| * **package:** removes `engine` section that points to npm@6 ([eecd12a](https://github.com/stalniy/casl/commit/eecd12ac49f56d6a0f57d1a57fb37487335b5f03)), closes [#417](https://github.com/stalniy/casl/issues/417) | ||
| * **README:** removes explanation duplicated from intro guide ([6315aa7](https://github.com/stalniy/casl/commit/6315aa7eea681d76bda947a7d5353da39c48e005)) | ||
| * **types:** ensure `ForceSubject` generic parameter is preserved in resulting d.ts files ([e97e5fe](https://github.com/stalniy/casl/commit/e97e5fe012e48553ae61a42f8c8240506056afed)) | ||
| * **types:** makes parameters of `AbilityClass` optional ([e7d0815](https://github.com/stalniy/casl/commit/e7d0815bfc2e18f4158bf5464b844fd55be92680)) | ||
| ### Code Refactoring | ||
| * **extra:** makes `fieldsFrom` option to be mandatory for `permittedFieldsOf` [skip release] ([df29b0d](https://github.com/stalniy/casl/commit/df29b0d7364ab1964d4d7b3b98212615beaa4952)) | ||
| * **ruleIndex:** `detectSubjectType` option is now responsible only for detecting subject type from objects [skip release] ([ebeaadc](https://github.com/stalniy/casl/commit/ebeaadc0974a3e1697b34b3d85d2510d65b73dbb)) | ||
| * **ruleIndex:** removes possibility to pass subject to `rulesFor` and `possibleRulesFor` [skip release] ([b8c324d](https://github.com/stalniy/casl/commit/b8c324d747f0a4fb8554931a85f1af211fe3c268)) | ||
| * **types:** restricts which utility types are exported by library ([e98618f](https://github.com/stalniy/casl/commit/e98618f34d0a29358644b6c11ce87398ffeb2437)) | ||
| ### Features | ||
| * **builder:** improves typings for AbilityBuilder [skip release] ([ebd4d17](https://github.com/stalniy/casl/commit/ebd4d17a355a2646467033118a3d6efee4321d27)), closes [#379](https://github.com/stalniy/casl/issues/379) | ||
| * **builder:** improves typings of `AbilityBuilder['can']` and `AbilityBuilder['cannot']` methods [skip release] ([98ffbfc](https://github.com/stalniy/casl/commit/98ffbfc58fbfa810020e9b79d22d27d67563e5b7)), closes [#333](https://github.com/stalniy/casl/issues/333) | ||
| * **esm:** adds ESM support for latest Node.js through `exports` prop in package.json ([cac2506](https://github.com/stalniy/casl/commit/cac2506a80c18f194210c2d89108d1d094751fa4)), closes [#331](https://github.com/stalniy/casl/issues/331) | ||
| * **extra:** adds `rulesToAST` that converts rules into [@ucast](https://github.com/ucast) AST ([55fd6ee](https://github.com/stalniy/casl/commit/55fd6eeb9e0b71bb38f1db8cfb87ba7fad391988)), closes [#350](https://github.com/stalniy/casl/issues/350) | ||
| ### Performance Improvements | ||
| * **ability:** creates conditions and field matcher lazily ([4ae7799](https://github.com/stalniy/casl/commit/4ae779902c0a59c6dea6f3535ba2fd80cac691da)) | ||
| * **ability:** replaces object for storing index with ES6 Map ([d1fa117](https://github.com/stalniy/casl/commit/d1fa117c090e41c2b5f176f467e7561456961c78)) | ||
| * **events:** converts LinkedItem into POJO and regular functions ([6f2de73](https://github.com/stalniy/casl/commit/6f2de73550d7304bc22487d93ea9e5b9dc6a3b64)) | ||
| * **events:** handles event removal in space efficient way ([71246e2](https://github.com/stalniy/casl/commit/71246e220b6c1abddd553ff8684cdc8732106d57)) | ||
| * **events:** moves out side-effect from `LinkedItem` constructor ([3657c7f](https://github.com/stalniy/casl/commit/3657c7f6d1e24ef2f4a73d1fadee12a529b8148b)) | ||
| * **events:** utilizes LinkedList for storing event handlers ([e2fd265](https://github.com/stalniy/casl/commit/e2fd2656e06af1883ac3f428b97add1ce14727fb)) | ||
| * **extra:** replaces object with `Set` in `permittedFieldsOf` ([a9260d1](https://github.com/stalniy/casl/commit/a9260d17c71bfe1c497f058c2b080b102cb28ed6)) | ||
| * **rule:** ensures conditions/field matcher created only when we have object/field to check ([110a69d](https://github.com/stalniy/casl/commit/110a69d049e8abd6711f8d111af0a28e8d079428)) | ||
| * **ruleIndex:** removes subject type detection from `_buildIndexFor` ([13fe934](https://github.com/stalniy/casl/commit/13fe93437fa3f9f5604a962eecaac02c663b39cb)) | ||
| * **rules:** improves merging logic of rules of subject and `manage all` ([6f8a13a](https://github.com/stalniy/casl/commit/6f8a13a507a2caafe7d6877c9a6f28cdd56c59bc)) | ||
| ### Reverts | ||
| * **builder:** reverts back `AbilityBuilder` generic parameter ([aa7b45f](https://github.com/stalniy/casl/commit/aa7b45f69c4fc7b603b8b5be3e9982d370d3398a)) | ||
| * **extra:** makes `rulesToQuery` return an object with `Object` prototype ([dcb7254](https://github.com/stalniy/casl/commit/dcb725471f125d4f7989f116ebf729dee7f53bef)) | ||
| ### BREAKING CHANGES | ||
| * **types:** types `AliasesMap`, `TaggedInterface`, `AbilityTupleType`, `ToAbilityTypes`, `AnyObject` are no longer exported by the library | ||
| * **extra:** makes `fieldsFrom` option to be mandatory for `permittedFieldsO | ||
| f`. This reduces confusion around why `permittedFieldsOf` returns empty array when user can manage entity fields. So, now this logic is just explicit and clear | ||
| **Before** | ||
| ```js | ||
| import { defineAbility } from '@casl/ability'; | ||
| import { permittedFieldsOf } from '@casl/ability/extra'; | ||
| const ability = defineAbility((can) => { | ||
| can('read', 'Article'); | ||
| }); | ||
| const fields = permittedFieldsOf(ability, 'read', 'Article'); // [] | ||
| ``` | ||
| **After** | ||
| ```js | ||
| import { defineAbility } from '@casl/ability'; | ||
| import { permittedFieldsOf } from '@casl/ability/extra'; | ||
| const ability = defineAbility((can) => { | ||
| can('read', 'Article'); | ||
| }); | ||
| const ARTICLE_FIELDS = ['id', 'title', 'description']; | ||
| const fields = permittedFieldsOf(ability, 'read', 'Article', { | ||
| fieldsFrom: rule => rule.fields || ARTICLE_FIELDS | ||
| }); // ['id', 'title', 'description'] | ||
| ``` | ||
| * **ruleIndex:** string and class (or function constructor) are the only possible subject types for now. `detectSubjectType` is now responsible only for detecting subject type from object | ||
| **Before** | ||
| When providing subject type it was important to handle cases when passed in argument is a string or function. As an alternative it was possible to call built-in `detectSubjectType` which could catch this cases: | ||
| ```js | ||
| import { Ability } from '@casl/ability'; | ||
| const ability = new Ability([], { | ||
| detectSubjectType(object) { | ||
| if (object && typeof object === 'object') { | ||
| return object.__typename; | ||
| } | ||
| return detectSubjectType(object); | ||
| }); | ||
| ``` | ||
| **After** | ||
| There is no need to handle subject type values in `detectSubjectType` function anymore. It's now handled internally: | ||
| ```js | ||
| import { Ability } from '@casl/ability'; | ||
| const ability = new Ability([], { | ||
| detectSubjectType: object => object.__typename | ||
| }); | ||
| ``` | ||
| Also it's important to note that if you want it's no longer possible to use classes and strings as subject types interchangably together as it was before. Now, if you want to use classes, you should use them everywhere: | ||
| **Before** | ||
| ```js | ||
| import { defineAbility } from '@casl/ability'; | ||
| class Post {} | ||
| const ability = defineAbility((can) => { | ||
| can('read', Post); | ||
| can('update', 'Post'); | ||
| }); | ||
| ability.can('read', 'Post') // true | ||
| ability.can('read', Post) // true | ||
| ability.can('update', Post) // true | ||
| ``` | ||
| **After** | ||
| ```js | ||
| import { defineAbility } from '@casl/ability'; | ||
| class Post {} | ||
| const ability = defineAbility((can) => { | ||
| can('read', Post); | ||
| can('update', 'Post'); | ||
| }); | ||
| ability.can('read', 'Post') // false, 'Post' and Post are considered different now | ||
| ability.can('read', Post) // true | ||
| ability.can('update', Post) // false | ||
| ``` | ||
| * **ruleIndex:** `rulesFor`, `possibleRulesFor`, `rulesToQuery`, `ruleToAST`, `rulesToFields` accepts only subject type now! | ||
| **Before** | ||
| ```js | ||
| import { Ability } from '@casl/ability'; | ||
| const ability = new Ability([ | ||
| { action: 'read', subject: 'Post' } | ||
| ]); | ||
| class Post {} | ||
| console.log(ability.rulesFor('read', new Post())); // [Rule] | ||
| console.log(ability.rulesFor('read', 'Post')); // [Rule] | ||
| ``` | ||
| **After** | ||
| ```js | ||
| import { Ability } from '@casl/ability'; | ||
| const ability = new Ability([ | ||
| { action: 'read', subject: 'Post' } | ||
| ]); | ||
| class Post {} | ||
| console.log(ability.rulesFor('read', new Post())); // throws exception | ||
| console.log(ability.rulesFor('read', 'Post')); // [Rule] | ||
| ``` | ||
| Other functions and methods have the same behavior | ||
| * **builder:** changes main generic parameter to be a class instead of instance and makes `defineAbility` to accept options as the 2nd argument. | ||
| **Before** | ||
| ```ts | ||
| import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; | ||
| const resolveAction = (action: string) => {/* custom implementation */ }; | ||
| const ability = defineAbility({ resolveAction }, (can) => can('read', 'Item')); | ||
| const builder = new AbilityBuilder<Ability>(Ability); | ||
| ``` | ||
| **After** | ||
| ```ts | ||
| import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; | ||
| const resolveAction = (action: string) => {/* custom implementation */ }; | ||
| const ability = defineAbility((can) => can('read', 'Item'), { resolveAction }); | ||
| const builder = new AbilityBuilder(Ability); // first argument is now mandatory! | ||
| ``` | ||
| The 1st parameter to `AbilityBuilder` is now madatory. This allows to infer generic parameters from it and makes AbilityType that is built to be explicit. | ||
| * **builder:** `can` and `cannot` methods of `AbilityBuilder` now restricts what fields and operators can be used inside conditions (i.e., `MongoQuery`). Also these methods now suggests object fields based on passed instance | ||
| **Before** | ||
| ```ts | ||
| import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; | ||
| interface Person { | ||
| kind: 'Person' | ||
| firstName: string | ||
| lastName: string | ||
| age: number | ||
| address: { | ||
| street: string | ||
| city: string | ||
| } | ||
| } | ||
| type AppAbility = Ability<['read', Person | Person['kind']]>; | ||
| cons AppAbility = Ability as AbilityClass<AppAbility>; | ||
| cons { can } = new AbilityBuilder(AppAbility); | ||
| can('read', 'Person', { | ||
| 'address.street': 'Somewhere in the world', | ||
| fistName: 'John' // unintentional typo | ||
| }); | ||
| can('read', 'Person', ['fistName', 'lastName'], { // no intellisense for fields | ||
| age: { $gt: 18 } | ||
| }) | ||
| ``` | ||
| **After** | ||
| Because provided keys in the example above doesn't exist on `Person` interface, TypeScript throws an error. So, we are safe from typos! But what about dot notation? It's also supported but in more typesafe way: | ||
| ```ts | ||
| import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; | ||
| interface Person { | ||
| kind: 'Person' | ||
| firstName: string | ||
| lastName: string | ||
| age: number | ||
| address: { | ||
| street: string | ||
| city: string | ||
| } | ||
| } | ||
| type AppAbility = Ability<['read', Person | Person['kind']]>; | ||
| cons AppAbility = Ability as AbilityClass<AppAbility>; | ||
| cons { can } = new AbilityBuilder(AppAbility); | ||
| interface PersonQuery extends Person { | ||
| 'address.street': Person['address']['street'] | ||
| 'address.city': Person['address']['city'] | ||
| } | ||
| can<PersonQuery>('read', 'Person', { | ||
| 'address.street': 'Somewhere in the world', | ||
| fistName: 'John' // unintentional typo | ||
| }); | ||
| can<PersonQuery>('read', 'Person', ['firstName', 'lastName'], { | ||
| age: { $gt: 18 } | ||
| }) | ||
| ``` | ||
| Intellisense and type checking for fields is also implemented! To be able to use wildcards in fields just add additional generic parameter: | ||
| ```ts | ||
| can<PersonQuery, 'address.*'>('read', 'Person', ['firstName', 'address.*'], { | ||
| age: { $gt: 18 } | ||
| }) | ||
| ``` | ||
| # [5.1.0-next.15](https://github.com/stalniy/casl/compare/@casl/ability@5.1.0-next.14...@casl/ability@5.1.0-next.15) (2020-12-20) | ||
@@ -7,0 +290,0 @@ |
+5
-4
| { | ||
| "name": "@casl/ability", | ||
| "version": "5.1.0-next.15", | ||
| "version": "5.1.0", | ||
| "description": "CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access", | ||
@@ -26,3 +26,3 @@ "funding": "https://github.com/stalniy/casl/blob/master/BACKERS.md", | ||
| }, | ||
| "homepage": "https://stalniy.github.io/casl/", | ||
| "homepage": "https://casl.js.org", | ||
| "publishConfig": { | ||
@@ -34,3 +34,4 @@ "access": "public" | ||
| "build.extra": "rollup -c ../../rollup.config.js -i src/extra.ts -n casl.extra -g @ucast/mongo2js:ucast.mongo2js", | ||
| "build.types": "rm -rf dist/types/* && tsc -p tsconfig.build.json && cp index.metadata.json dist/types", | ||
| "build.types": "tsc -p tsconfig.build.json && cp index.metadata.json dist/types", | ||
| "prebuild": "rm -rf dist/*", | ||
| "build": "npm run build.types && npm run build.core && npm run build.extra", | ||
@@ -69,3 +70,3 @@ "lint": "eslint --ext .js,.ts src/ spec/", | ||
| "@types/node": "^14.0.5", | ||
| "@typescript-eslint/eslint-plugin": "4.5.0", | ||
| "@typescript-eslint/eslint-plugin": "4.7.0", | ||
| "chai": "^4.1.0", | ||
@@ -72,0 +73,0 @@ "chai-spies": "^1.0.0", |
| function wrapArray(value) { | ||
| return Array.isArray(value) ? value : [value]; | ||
| } | ||
| function setByPath(object, path, value) { | ||
| let ref = object; | ||
| let lastKey = path; | ||
| if (path.indexOf('.') !== -1) { | ||
| const keys = path.split('.'); | ||
| lastKey = keys.pop(); | ||
| ref = keys.reduce((res, prop) => { | ||
| res[prop] = res[prop] || {}; | ||
| return res[prop]; | ||
| }, object); | ||
| } | ||
| ref[lastKey] = value; | ||
| } | ||
| function rulesToQuery(ability, ...args) { | ||
| const [action, subject, convert] = args; | ||
| const query = {}; | ||
| const rules = ability.rulesFor(action, subject); | ||
| for (let i = 0; i < rules.length; i++) { | ||
| const rule = rules[i]; | ||
| const op = rule.inverted ? '$and' : '$or'; | ||
| if (!rule.conditions) { | ||
| if (rule.inverted) { | ||
| break; | ||
| } else { | ||
| delete query[op]; | ||
| return query; | ||
| } | ||
| } else { | ||
| query[op] = query[op] || []; | ||
| query[op].push(convert(rule)); | ||
| } | ||
| } | ||
| return query.$or ? query : null; | ||
| } | ||
| function rulesToFields(ability, ...[action, subject]) { | ||
| return ability.rulesFor(action, subject).filter(rule => !rule.inverted && rule.conditions).reduce((values, rule) => { | ||
| const conditions = rule.conditions; | ||
| return Object.keys(conditions).reduce((fields, fieldName) => { | ||
| const value = conditions[fieldName]; | ||
| if (!value || value.constructor !== Object) { | ||
| setByPath(fields, fieldName, value); | ||
| } | ||
| return fields; | ||
| }, values); | ||
| }, {}); | ||
| } | ||
| const getRuleFields = rule => rule.fields; | ||
| function deleteKey(key) { | ||
| delete this[key]; | ||
| } | ||
| function setKey(key) { | ||
| this[key] = true; | ||
| } | ||
| function permittedFieldsOf(ability, action, subject, options = {}) { | ||
| const fieldsFrom = options.fieldsFrom || getRuleFields; | ||
| const uniqueFields = ability.possibleRulesFor(action, subject).filter(rule => rule.matchesConditions(subject)).reverse().reduce((fields, rule) => { | ||
| const names = fieldsFrom(rule); | ||
| if (names) { | ||
| const toggle = rule.inverted ? deleteKey : setKey; | ||
| names.forEach(toggle, fields); | ||
| } | ||
| return fields; | ||
| }, {}); | ||
| return Object.keys(uniqueFields); | ||
| } | ||
| const joinIfArray = value => Array.isArray(value) ? value.join(',') : value; | ||
| function packRules(rules, packSubject) { | ||
| return rules.map(rule => { | ||
| // eslint-disable-line | ||
| const packedRule = [joinIfArray(rule.action || rule.actions), typeof packSubject === 'function' ? wrapArray(rule.subject).map(packSubject).join(',') : joinIfArray(rule.subject), rule.conditions || 0, rule.inverted ? 1 : 0, rule.fields ? joinIfArray(rule.fields) : 0, rule.reason || '']; | ||
| while (!packedRule[packedRule.length - 1]) packedRule.pop(); | ||
| return packedRule; | ||
| }); | ||
| } | ||
| function unpackRules(rules, unpackSubject) { | ||
| return rules.map(([action, subject, conditions, inverted, fields, reason]) => { | ||
| const subjects = subject.split(','); | ||
| const rule = { | ||
| inverted: !!inverted, | ||
| action: action.split(','), | ||
| subject: typeof unpackSubject === 'function' ? subjects.map(unpackSubject) : subjects | ||
| }; | ||
| if (conditions) { | ||
| rule.conditions = conditions; | ||
| } | ||
| if (fields) { | ||
| rule.fields = fields.split(','); | ||
| } | ||
| if (reason) { | ||
| rule.reason = reason; | ||
| } | ||
| return rule; | ||
| }); | ||
| } | ||
| export { packRules, permittedFieldsOf, rulesToFields, rulesToQuery, unpackRules }; | ||
| //# sourceMappingURL=extra.js.map |
| {"version":3,"file":"extra.js","sources":["../../src/utils.ts","../../src/extra.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>,\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport const identity = <T>(x: T) => x;\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n","import { PureAbility, AnyAbility } from './PureAbility';\nimport { RuleOf, Generics } from './RuleIndex';\nimport { RawRule } from './RawRule';\nimport { Rule } from './Rule';\nimport { setByPath, wrapArray } from './utils';\nimport {\n AbilityParameters,\n AnyObject,\n SubjectType,\n AbilityTuple,\n CanParameters,\n Abilities,\n} from './types';\n\nexport type RuleToQueryConverter<T extends AnyAbility> = (rule: RuleOf<T>) => object;\nexport interface AbilityQuery {\n $or?: object[]\n $and?: object[]\n}\n\ntype RulesToQueryRestArgs<T extends Abilities, ConvertRule> = AbilityParameters<\nT,\nT extends AbilityTuple\n ? (action: T[0], subject: T[1], convert: ConvertRule) => 0\n : never,\n(action: never, subject: never, convert: ConvertRule) => 0\n>;\n\nexport function rulesToQuery<T extends AnyAbility>(\n ability: T,\n ...args: RulesToQueryRestArgs<Generics<T>['abilities'], RuleToQueryConverter<T>>\n): AbilityQuery | null {\n const [action, subject, convert] = args;\n const query: AbilityQuery = {};\n const rules = ability.rulesFor(action, subject) as RuleOf<T>[];\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i];\n const op = rule.inverted ? '$and' : '$or';\n\n if (!rule.conditions) {\n if (rule.inverted) {\n break;\n } else {\n delete query[op];\n return query;\n }\n } else {\n query[op] = query[op] || [];\n query[op]!.push(convert(rule));\n }\n }\n\n return query.$or ? query : null;\n}\n\nexport function rulesToFields<T extends PureAbility<any, AnyObject>>(\n ability: T,\n ...[action, subject]: CanParameters<Generics<T>['abilities'], false>\n): AnyObject {\n return ability.rulesFor(action, subject)\n .filter(rule => !rule.inverted && rule.conditions)\n .reduce((values, rule) => {\n const conditions = rule.conditions!;\n\n return Object.keys(conditions).reduce((fields, fieldName) => {\n const value = conditions[fieldName];\n\n if (!value || (value as any).constructor !== Object) {\n setByPath(fields, fieldName, value);\n }\n\n return fields;\n }, values);\n }, {} as AnyObject);\n}\n\nconst getRuleFields = (rule: RuleOf<AnyAbility>) => rule.fields;\n\nexport type GetRuleFields<R extends Rule<any, any>> = (rule: R) => string[] | undefined;\n\nexport interface PermittedFieldsOptions<T extends AnyAbility> {\n fieldsFrom?: GetRuleFields<RuleOf<T>>\n}\n\nfunction deleteKey(this: Record<string, any>, key: string) {\n delete this[key];\n}\n\nfunction setKey(this: Record<string, any>, key: string) {\n this[key] = true;\n}\n\nexport function permittedFieldsOf<T extends AnyAbility>(\n ability: T,\n action: Parameters<T['can']>[0],\n subject: Parameters<T['can']>[1],\n options: PermittedFieldsOptions<T> = {},\n): string[] {\n const fieldsFrom = options.fieldsFrom || getRuleFields;\n const uniqueFields = ability.possibleRulesFor(action, subject)\n .filter(rule => rule.matchesConditions(subject))\n .reverse()\n .reduce((fields, rule) => {\n const names = fieldsFrom(rule);\n\n if (names) {\n const toggle = rule.inverted ? deleteKey : setKey;\n names.forEach(toggle, fields);\n }\n\n return fields;\n }, {} as Record<string, true>);\n\n return Object.keys(uniqueFields);\n}\n\nconst joinIfArray = (value: string | string[]) => Array.isArray(value) ? value.join(',') : value;\n\nexport type PackRule<T extends RawRule<any, any>> =\n [string, string] |\n [string, string, T['conditions']] |\n [string, string, T['conditions'] | 0, 1] |\n [string, string, T['conditions'] | 0, 1 | 0, string] |\n [string, string, T['conditions'] | 0, 1 | 0, string | 0, string];\n\nexport type PackSubjectType<T extends SubjectType> = (type: T) => string;\n\nexport function packRules<T extends RawRule<any, any>>(\n rules: T[],\n packSubject?: PackSubjectType<T['subject']>,\n): PackRule<T>[] {\n return rules.map((rule) => { // eslint-disable-line\n const packedRule: PackRule<T> = [\n joinIfArray((rule as any).action || (rule as any).actions),\n typeof packSubject === 'function'\n ? wrapArray(rule.subject).map(packSubject).join(',')\n : joinIfArray(rule.subject),\n rule.conditions || 0,\n rule.inverted ? 1 : 0,\n rule.fields ? joinIfArray(rule.fields) : 0,\n rule.reason || '',\n ];\n\n while (!packedRule[packedRule.length - 1]) packedRule.pop();\n\n return packedRule;\n });\n}\n\nexport type UnpackSubjectType<T extends SubjectType> = (type: string) => T;\n\nexport function unpackRules<T extends RawRule<any, any>>(\n rules: PackRule<T>[],\n unpackSubject?: UnpackSubjectType<T['subject']>,\n): T[] {\n return rules.map(([action, subject, conditions, inverted, fields, reason]) => {\n const subjects = subject.split(',');\n const rule = {\n inverted: !!inverted,\n action: action.split(','),\n subject: typeof unpackSubject === 'function'\n ? subjects.map(unpackSubject)\n : subjects,\n } as T;\n\n if (conditions) {\n rule.conditions = conditions;\n }\n\n if (fields) {\n rule.fields = fields.split(',');\n }\n\n if (reason) {\n rule.reason = reason;\n }\n\n return rule;\n });\n}\n"],"names":["wrapArray","value","Array","isArray","setByPath","object","path","ref","lastKey","indexOf","keys","split","pop","reduce","res","prop","rulesToQuery","ability","args","action","subject","convert","query","rules","rulesFor","i","length","rule","op","inverted","conditions","push","$or","rulesToFields","filter","values","Object","fields","fieldName","constructor","getRuleFields","deleteKey","key","setKey","permittedFieldsOf","options","fieldsFrom","uniqueFields","possibleRulesFor","matchesConditions","reverse","names","toggle","forEach","joinIfArray","join","packRules","packSubject","map","packedRule","actions","reason","unpackRules","unpackSubject","subjects"],"mappings":"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"} |
| import { createQueryTester, $eq, $ne, $lt, $lte, $gt, $gte, $in, $nin, $all, $size, $regex, $elemMatch, $exists } from 'sift'; | ||
| function wrapArray(value) { | ||
| return Array.isArray(value) ? value : [value]; | ||
| } | ||
| const TYPE_FIELD = '__caslSubjectType__'; | ||
| function setSubjectType(type, object) { | ||
| if (object) { | ||
| if (!object.hasOwnProperty(TYPE_FIELD)) { | ||
| Object.defineProperty(object, TYPE_FIELD, { | ||
| value: type | ||
| }); | ||
| } else if (type !== object[TYPE_FIELD]) { | ||
| throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`); | ||
| } | ||
| } | ||
| return object; | ||
| } | ||
| function detectSubjectType(subject) { | ||
| if (!subject) { | ||
| return 'all'; | ||
| } | ||
| if (typeof subject === 'string') { | ||
| return subject; | ||
| } | ||
| if (subject.hasOwnProperty(TYPE_FIELD)) { | ||
| return subject[TYPE_FIELD]; | ||
| } | ||
| const Type = typeof subject === 'function' ? subject : subject.constructor; | ||
| return Type.modelName || Type.name; | ||
| } | ||
| function expandActions(aliasMap, rawActions) { | ||
| let actions = wrapArray(rawActions); | ||
| let i = 0; | ||
| while (i < actions.length) { | ||
| const action = actions[i++]; | ||
| if (aliasMap.hasOwnProperty(action)) { | ||
| actions = actions.concat(aliasMap[action]); | ||
| } | ||
| } | ||
| return actions; | ||
| } | ||
| function assertAliasMap(aliasMap) { | ||
| if (aliasMap.manage) { | ||
| throw new Error('Cannot add alias for "manage" action because it is reserved'); | ||
| } | ||
| Object.keys(aliasMap).forEach(alias => { | ||
| const hasError = alias === aliasMap[alias] || Array.isArray(aliasMap[alias]) && (aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1); | ||
| if (hasError) { | ||
| throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`); | ||
| } | ||
| }); | ||
| } | ||
| const identity = x => x; | ||
| function createAliasResolver(aliasMap) { | ||
| if (process.env.NODE_ENV !== 'production') { | ||
| assertAliasMap(aliasMap); | ||
| } | ||
| return action => expandActions(aliasMap, action); | ||
| } | ||
| class Rule { | ||
| constructor(rule, options) { | ||
| this._matchConditions = void 0; | ||
| this._matchField = void 0; | ||
| this.action = options.resolveAction(rule.actions || rule.action); | ||
| this.subject = rule.subject; | ||
| this.inverted = !!rule.inverted; | ||
| this.conditions = rule.conditions; | ||
| this.reason = rule.reason; | ||
| this.fields = !rule.fields || rule.fields.length === 0 ? undefined : wrapArray(rule.fields); | ||
| if ('actions' in rule) { | ||
| // eslint-disable-next-line | ||
| console.warn('Rule `actions` field is deprecated. Use `action` field instead'); | ||
| } | ||
| if (this.conditions && options.conditionsMatcher) { | ||
| this._matchConditions = options.conditionsMatcher(this.conditions); | ||
| } | ||
| if (this.fields && options.fieldMatcher) { | ||
| this._matchField = options.fieldMatcher(this.fields); | ||
| } | ||
| } | ||
| matchesConditions(object) { | ||
| if (!this._matchConditions) { | ||
| return true; | ||
| } | ||
| if (!object || typeof object === 'string' || typeof object === 'function') { | ||
| return !this.inverted; | ||
| } | ||
| return this._matchConditions(object); | ||
| } | ||
| matchesField(field) { | ||
| if (!this._matchField) { | ||
| return true; | ||
| } | ||
| if (!field) { | ||
| return !this.inverted; | ||
| } | ||
| return this._matchField(field); | ||
| } | ||
| } | ||
| class RulesAnalyzer { | ||
| constructor(hasRules) { | ||
| this._isAllInverted = void 0; | ||
| this._hasPerFieldRules = false; | ||
| this._hasRuleWithEmptyFields = false; | ||
| this._isAllInverted = hasRules; | ||
| this._analyze = this._analyze.bind(this); | ||
| } | ||
| _analyze({ | ||
| fields, | ||
| inverted | ||
| }) { | ||
| this._isAllInverted = this._isAllInverted && !!inverted; | ||
| if (!this._hasRuleWithEmptyFields && Array.isArray(fields) && !fields.length) { | ||
| this._hasRuleWithEmptyFields = true; | ||
| } | ||
| if (!this._hasPerFieldRules && fields && fields.length) { | ||
| this._hasPerFieldRules = true; | ||
| } | ||
| } | ||
| _validate(ruleOptions) { | ||
| if (this._isAllInverted) { | ||
| // eslint-disable-next-line | ||
| console.warn('Make sure your ability has direct rules, not only inverted ones. Otherwise `ability.can` will always return `false`.'); | ||
| } | ||
| if (this._hasRuleWithEmptyFields) { | ||
| // eslint-disable-next-line | ||
| console.warn('[error in next major version]: There are rules with `fields` property being an empty array. This results in the same as not passing fields at all. Make sure to remove empty array or pass fields.'); | ||
| } | ||
| if (this._hasPerFieldRules && !ruleOptions.fieldMatcher) { | ||
| throw new Error('Field level restrictions are ignored because "fieldMatcher" option is not specified. Did you unintentionally used PureAbility instead of Ability?'); | ||
| } | ||
| } | ||
| } | ||
| class RuleIndex { | ||
| constructor(rules = [], options = {}) { | ||
| this._hasPerFieldRules = false; | ||
| this._mergedRules = Object.create(null); | ||
| this._events = Object.create(null); | ||
| this._indexedRules = Object.create(null); | ||
| this._rules = []; | ||
| this._ruleOptions = { | ||
| conditionsMatcher: options.conditionsMatcher, | ||
| fieldMatcher: options.fieldMatcher, | ||
| resolveAction: options.resolveAction || identity | ||
| }; | ||
| Object.defineProperty(this, 'detectSubjectType', { | ||
| value: options.detectSubjectType || options.subjectName || detectSubjectType | ||
| }); | ||
| Object.defineProperty(this, 'rules', { | ||
| get: () => this._rules | ||
| }); | ||
| this.update(rules); | ||
| } | ||
| update(rules) { | ||
| const event = { | ||
| rules, | ||
| ability: this, | ||
| target: this | ||
| }; | ||
| this._emit('update', event); | ||
| this._mergedRules = Object.create(null); | ||
| const analyser = new RulesAnalyzer(rules.length > 0); | ||
| const indexedRules = this._buildIndexFor(rules, analyser._analyze); | ||
| analyser._validate(this._ruleOptions); | ||
| this._indexedRules = indexedRules; | ||
| this._rules = rules; | ||
| this._hasPerFieldRules = analyser._hasPerFieldRules; | ||
| this._emit('updated', event); | ||
| return this; | ||
| } | ||
| _buildIndexFor(rawRules, iterator = identity) { | ||
| const indexedRules = Object.create(null); | ||
| for (let i = 0; i < rawRules.length; i++) { | ||
| iterator(rawRules[i], i); | ||
| const rule = new Rule(rawRules[i], this._ruleOptions); | ||
| const priority = rawRules.length - i - 1; | ||
| const actions = wrapArray(rule.action); | ||
| const subjects = wrapArray(rule.subject); | ||
| for (let k = 0; k < subjects.length; k++) { | ||
| const subject = this.detectSubjectType(subjects[k]); | ||
| indexedRules[subject] = indexedRules[subject] || Object.create(null); | ||
| for (let j = 0; j < actions.length; j++) { | ||
| const action = actions[j]; | ||
| indexedRules[subject][action] = indexedRules[subject][action] || Object.create(null); | ||
| indexedRules[subject][action][priority] = rule; | ||
| } | ||
| } | ||
| } | ||
| return indexedRules; | ||
| } | ||
| possibleRulesFor(...args) { | ||
| const [action, subject] = args; | ||
| const subjectName = this.detectSubjectType(subject); | ||
| const mergedRules = this._mergedRules; | ||
| const key = `${subjectName}_${action}`; | ||
| if (!mergedRules[key]) { | ||
| mergedRules[key] = this._mergeRulesFor(action, subjectName); | ||
| } | ||
| return mergedRules[key]; | ||
| } | ||
| _mergeRulesFor(action, subjectName) { | ||
| const subjects = subjectName === 'all' ? [subjectName] : [subjectName, 'all']; | ||
| const mergedRules = subjects.reduce((rules, subjectType) => { | ||
| const subjectRules = this._indexedRules[subjectType]; | ||
| if (!subjectRules) { | ||
| return rules; | ||
| } | ||
| return Object.assign(rules, subjectRules[action], subjectRules.manage); | ||
| }, []); // TODO: think whether there is a better way to prioritize rules | ||
| // or convert sparse array to regular one | ||
| return mergedRules.filter(Boolean); | ||
| } | ||
| rulesFor(...args) { | ||
| const [action, subject, field] = args; | ||
| const rules = this.possibleRulesFor(action, subject); | ||
| if (field && typeof field !== 'string') { | ||
| throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details'); | ||
| } | ||
| if (!this._hasPerFieldRules) { | ||
| return rules; | ||
| } | ||
| return rules.filter(rule => rule.matchesField(field)); | ||
| } | ||
| on(event, handler) { | ||
| const events = this._events; | ||
| let isAttached = true; | ||
| if (!events[event]) { | ||
| events[event] = []; | ||
| } | ||
| events[event].push(handler); | ||
| return () => { | ||
| if (isAttached) { | ||
| const index = events[event].indexOf(handler); | ||
| events[event].splice(index, 1); | ||
| isAttached = false; | ||
| } | ||
| }; | ||
| } | ||
| _emit(eventName, event) { | ||
| const handlers = this._events[eventName]; | ||
| if (handlers) { | ||
| handlers.slice(0).forEach(handler => handler(event)); | ||
| } | ||
| } | ||
| } | ||
| class PureAbility extends RuleIndex { | ||
| can(...args) { | ||
| const rule = this.relevantRuleFor(...args); | ||
| return !!rule && !rule.inverted; | ||
| } | ||
| relevantRuleFor(...args) { | ||
| const rules = this.rulesFor(...args); | ||
| const subject = args[1]; | ||
| for (let i = 0; i < rules.length; i++) { | ||
| if (rules[i].matchesConditions(subject)) { | ||
| return rules[i]; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| cannot(...args) { | ||
| return !this.can(...args); | ||
| } | ||
| } | ||
| const defaultOperations = { | ||
| $eq, | ||
| $ne, | ||
| $lt, | ||
| $lte, | ||
| $gt, | ||
| $gte, | ||
| $in, | ||
| $nin, | ||
| $all, | ||
| $size, | ||
| $regex, | ||
| $elemMatch, | ||
| $exists | ||
| }; | ||
| function buildMongoQueryMatcher(operations) { | ||
| const options = { | ||
| operations: Object.assign({}, defaultOperations, operations) | ||
| }; | ||
| return conditions => createQueryTester(conditions, options); | ||
| } | ||
| const mongoQueryMatcher = buildMongoQueryMatcher({}); | ||
| const REGEXP_SPECIAL_CHARS = /[-/\\^$+?.()|[\]{}]/g; | ||
| const REGEXP_ANY = /\.?\*+\.?/g; | ||
| const REGEXP_STARS = /\*+/; | ||
| const REGEXP_DOT = /\./g; | ||
| function detectRegexpPattern(match, index, string) { | ||
| const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.' ? '+' : '*'; | ||
| const matcher = match.indexOf('**') === -1 ? '[^.]' : '.'; | ||
| const pattern = match.replace(REGEXP_DOT, '\\$&').replace(REGEXP_STARS, matcher + quantifier); | ||
| return index + match.length === string.length ? `(?:${pattern})?` : pattern; | ||
| } | ||
| function escapeRegexp(match, index, string) { | ||
| if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) { | ||
| return match; | ||
| } | ||
| return `\\${match}`; | ||
| } | ||
| function createPattern(fields) { | ||
| const patterns = fields.map(field => field.replace(REGEXP_SPECIAL_CHARS, escapeRegexp).replace(REGEXP_ANY, detectRegexpPattern)); | ||
| const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0]; | ||
| return new RegExp(`^${pattern}$`); | ||
| } | ||
| const fieldPatternMatcher = fields => { | ||
| let pattern; | ||
| return field => { | ||
| if (typeof pattern === 'undefined') { | ||
| pattern = fields.every(f => f.indexOf('*') === -1) ? null : createPattern(fields); | ||
| } | ||
| return pattern === null ? fields.indexOf(field) !== -1 : pattern.test(field); | ||
| }; | ||
| }; | ||
| class Ability extends PureAbility { | ||
| constructor(rules, options) { | ||
| super(rules, Object.assign({ | ||
| conditionsMatcher: mongoQueryMatcher, | ||
| fieldMatcher: fieldPatternMatcher | ||
| }, options)); | ||
| } | ||
| } | ||
| class RuleBuilder { | ||
| constructor(rule) { | ||
| this.rule = rule; | ||
| } | ||
| because(reason) { | ||
| this.rule.reason = reason; | ||
| return this; | ||
| } | ||
| } | ||
| class AbilityBuilder { | ||
| constructor(AbilityType = PureAbility) { | ||
| this.rules = []; | ||
| this._AbilityType = AbilityType; | ||
| const self = this; | ||
| self.can = self.can.bind(self); | ||
| self.cannot = self.cannot.bind(self); | ||
| self.build = self.build.bind(self); | ||
| } | ||
| can(action, subject, conditionsOrFields, conditions) { | ||
| const rule = { | ||
| action | ||
| }; | ||
| if (subject) { | ||
| rule.subject = subject; | ||
| if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') { | ||
| rule.fields = conditionsOrFields; | ||
| } else if (typeof conditionsOrFields !== 'undefined') { | ||
| rule.conditions = conditionsOrFields; | ||
| } | ||
| if (typeof conditions !== 'undefined') { | ||
| rule.conditions = conditions; | ||
| } | ||
| } | ||
| this.rules.push(rule); | ||
| return new RuleBuilder(rule); | ||
| } | ||
| cannot(action, subject, conditionsOrFields, conditions) { | ||
| const builder = this.can(action, subject, conditionsOrFields, conditions); | ||
| builder.rule.inverted = true; | ||
| return builder; | ||
| } | ||
| build(options) { | ||
| return new this._AbilityType(this.rules, options); | ||
| } | ||
| } | ||
| function defineAbility(params, dsl) { | ||
| let options; | ||
| let define; | ||
| if (typeof params === 'function') { | ||
| define = params; | ||
| options = {}; | ||
| } else if (typeof dsl === 'function') { | ||
| options = params; | ||
| define = dsl; | ||
| } else { | ||
| throw new Error('`defineAbility` expects to receive either options and dsl function or only dsl function'); | ||
| } | ||
| const builder = new AbilityBuilder(Ability); | ||
| const result = define(builder.can, builder.cannot); | ||
| return result && typeof result.then === 'function' ? result.then(() => builder.build(options)) : builder.build(options); | ||
| } | ||
| const getDefaultErrorMessage = error => `Cannot execute "${error.action}" on "${error.subjectType}"`; | ||
| const NativeError = function NError(message) { | ||
| this.message = message; | ||
| }; | ||
| NativeError.prototype = Object.create(Error.prototype); | ||
| class ForbiddenError extends NativeError { | ||
| static setDefaultMessage(messageOrFn) { | ||
| this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn; | ||
| } | ||
| static from(ability) { | ||
| return new this(ability); | ||
| } | ||
| constructor(ability) { | ||
| super(''); | ||
| this.ability = void 0; | ||
| this.field = void 0; | ||
| this.ability = ability; | ||
| if (typeof Error.captureStackTrace === 'function') { | ||
| this.name = 'ForbiddenError'; | ||
| Error.captureStackTrace(this, this.constructor); | ||
| } | ||
| } | ||
| setMessage(message) { | ||
| this.message = message; | ||
| return this; | ||
| } | ||
| throwUnlessCan(...args) { | ||
| const rule = this.ability.relevantRuleFor(...args); | ||
| if (rule && !rule.inverted) { | ||
| return; | ||
| } | ||
| this.action = args[0]; | ||
| this.subject = args[1]; | ||
| this.subjectType = this.ability.detectSubjectType(args[1]); | ||
| this.field = args[2]; | ||
| const reason = rule ? rule.reason : ''; // eslint-disable-next-line no-underscore-dangle | ||
| this.message = this.message || reason || this.constructor._defaultErrorMessage(this); | ||
| throw this; // eslint-disable-line | ||
| } | ||
| } | ||
| ForbiddenError._defaultErrorMessage = getDefaultErrorMessage; | ||
| export { Ability, AbilityBuilder, ForbiddenError, PureAbility, buildMongoQueryMatcher, createAliasResolver, defineAbility, detectSubjectType, fieldPatternMatcher, getDefaultErrorMessage, mongoQueryMatcher, setSubjectType as subject, wrapArray }; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/Rule.ts","../../src/RulesAnalyzer.ts","../../src/RuleIndex.ts","../../src/PureAbility.ts","../../src/matchers/conditions.ts","../../src/matchers/field.ts","../../src/Ability.ts","../../src/AbilityBuilder.ts","../../src/ForbiddenError.ts"],"sourcesContent":["import { AnyObject, Subject, SubjectClass, ForcedSubject, AliasesMap } from './types';\n\nexport function wrapArray<T>(value: T[] | T): T[] {\n return Array.isArray(value) ? value : [value];\n}\n\nexport function setByPath(object: AnyObject, path: string, value: unknown): void {\n let ref = object;\n let lastKey = path;\n\n if (path.indexOf('.') !== -1) {\n const keys = path.split('.');\n\n lastKey = keys.pop()!;\n ref = keys.reduce((res, prop) => {\n res[prop] = res[prop] || {};\n return res[prop] as AnyObject;\n }, object);\n }\n\n ref[lastKey] = value;\n}\n\nconst TYPE_FIELD = '__caslSubjectType__';\nexport function setSubjectType<\n T extends string,\n U extends Record<PropertyKey, any>,\n>(type: T, object: U): U & ForcedSubject<T> {\n if (object) {\n if (!object.hasOwnProperty(TYPE_FIELD)) {\n Object.defineProperty(object, TYPE_FIELD, { value: type });\n } else if (type !== object[TYPE_FIELD]) {\n throw new Error(`Trying to cast object to subject type ${type} but previously it was casted to ${object[TYPE_FIELD]}`);\n }\n }\n\n return object as U & ForcedSubject<T>;\n}\n\nexport function detectSubjectType<T extends Subject>(subject?: T): string {\n if (!subject) {\n return 'all';\n }\n\n if (typeof subject === 'string') {\n return subject;\n }\n\n if (subject.hasOwnProperty(TYPE_FIELD)) {\n return (subject as any)[TYPE_FIELD];\n }\n\n const Type = typeof subject === 'function' ? subject : subject.constructor;\n return (Type as SubjectClass).modelName || Type.name;\n}\n\nexport function expandActions(aliasMap: AliasesMap, rawActions: string | string[]) {\n let actions = wrapArray(rawActions);\n let i = 0;\n\n while (i < actions.length) {\n const action = actions[i++];\n\n if (aliasMap.hasOwnProperty(action)) {\n actions = actions.concat(aliasMap[action]);\n }\n }\n\n return actions;\n}\n\nfunction assertAliasMap(aliasMap: AliasesMap) {\n if (aliasMap.manage) {\n throw new Error('Cannot add alias for \"manage\" action because it is reserved');\n }\n\n Object.keys(aliasMap).forEach((alias) => {\n const hasError = alias === aliasMap[alias]\n || Array.isArray(aliasMap[alias]) && (\n aliasMap[alias].indexOf(alias) !== -1 || aliasMap[alias].indexOf('manage') !== -1\n );\n\n if (hasError) {\n throw new Error(`Attempt to alias action to itself: ${alias} -> ${aliasMap[alias]}`);\n }\n });\n}\n\nexport const identity = <T>(x: T) => x;\nexport function createAliasResolver(aliasMap: AliasesMap) {\n if (process.env.NODE_ENV !== 'production') {\n assertAliasMap(aliasMap);\n }\n\n return (action: string | string[]) => expandActions(aliasMap, action);\n}\n","import { wrapArray } from './utils';\nimport {\n MatchConditions,\n RuleOptions,\n MatchField,\n Abilities,\n ToAbilityTypes,\n Normalize,\n} from './types';\nimport { RawRule } from './RawRule';\n\ntype Tuple<A extends Abilities> = Normalize<ToAbilityTypes<A>>;\n\nexport class Rule<A extends Abilities, C> {\n private readonly _matchConditions: MatchConditions | undefined;\n private readonly _matchField: MatchField<string> | undefined;\n public readonly action!: Tuple<A>[0] | Tuple<A>[0][];\n public readonly subject!: Tuple<A>[1] | Tuple<A>[1][];\n public readonly inverted!: boolean;\n public readonly conditions!: C | undefined;\n public readonly fields!: string[] | undefined;\n public readonly reason!: string | undefined;\n\n constructor(rule: RawRule<ToAbilityTypes<A>, C>, options: RuleOptions<A, C>) {\n this.action = options.resolveAction((rule as any).actions || (rule as any).action);\n this.subject = rule.subject;\n this.inverted = !!rule.inverted;\n this.conditions = rule.conditions;\n this.reason = rule.reason;\n this.fields = !rule.fields || rule.fields.length === 0\n ? undefined\n : wrapArray(rule.fields);\n\n if ('actions' in rule) {\n // eslint-disable-next-line\n console.warn('Rule `actions` field is deprecated. Use `action` field instead');\n }\n\n if (this.conditions && options.conditionsMatcher) {\n this._matchConditions = options.conditionsMatcher(this.conditions);\n }\n\n if (this.fields && options.fieldMatcher) {\n this._matchField = options.fieldMatcher(this.fields);\n }\n }\n\n matchesConditions(object: Normalize<A>[1] | undefined): boolean {\n if (!this._matchConditions) {\n return true;\n }\n\n if (!object || typeof object === 'string' || typeof object === 'function') {\n return !this.inverted;\n }\n\n return this._matchConditions(object as object);\n }\n\n matchesField(field: string | undefined): boolean {\n if (!this._matchField) {\n return true;\n }\n\n if (!field) {\n return !this.inverted;\n }\n\n return this._matchField(field);\n }\n}\n","import { RawRuleFrom } from './RawRule';\nimport { Abilities, RuleOptions } from './types';\n\nexport default class RulesAnalyzer<A extends Abilities, C> {\n public _isAllInverted: boolean;\n public _hasPerFieldRules: boolean = false;\n public _hasRuleWithEmptyFields: boolean = false;\n\n constructor(hasRules: boolean) {\n this._isAllInverted = hasRules;\n this._analyze = this._analyze.bind(this);\n }\n\n _analyze({ fields, inverted }: RawRuleFrom<A, C>) {\n this._isAllInverted = this._isAllInverted && !!inverted;\n\n if (!this._hasRuleWithEmptyFields && Array.isArray(fields) && !fields.length) {\n this._hasRuleWithEmptyFields = true;\n }\n\n if (!this._hasPerFieldRules && fields && fields.length) {\n this._hasPerFieldRules = true;\n }\n }\n\n _validate(ruleOptions: RuleOptions<A, C>) {\n if (this._isAllInverted) {\n // eslint-disable-next-line\n console.warn('Make sure your ability has direct rules, not only inverted ones. Otherwise `ability.can` will always return `false`.');\n }\n\n if (this._hasRuleWithEmptyFields) {\n // eslint-disable-next-line\n console.warn('[error in next major version]: There are rules with `fields` property being an empty array. This results in the same as not passing fields at all. Make sure to remove empty array or pass fields.');\n }\n\n if (this._hasPerFieldRules && !ruleOptions.fieldMatcher) {\n throw new Error('Field level restrictions are ignored because \"fieldMatcher\" option is not specified. Did you unintentionally used PureAbility instead of Ability?');\n }\n }\n}\n","import { Rule } from './Rule';\nimport { RawRuleFrom } from './RawRule';\nimport {\n DetectSubjectType,\n ResolveAction,\n CanParameters,\n Abilities,\n Normalize,\n ConditionsMatcher,\n FieldMatcher,\n RuleOptions,\n} from './types';\nimport { wrapArray, detectSubjectType, identity } from './utils';\nimport RulesAnalyzer from './RulesAnalyzer';\n\ntype AnyRuleIndex = RuleIndex<any, any, any>;\n\nexport interface RuleIndexOptions<A extends Abilities, Conditions> {\n /** @deprecated use \"detectSubjectType\" option instead */\n subjectName?: this['detectSubjectType']\n detectSubjectType?: DetectSubjectType<Normalize<A>[1]>\n conditionsMatcher?: ConditionsMatcher<Conditions>\n fieldMatcher?: FieldMatcher\n resolveAction?: ResolveAction<Normalize<A>[0]>\n}\n\nexport type Generics<T extends AnyRuleIndex> = T extends AnyRuleIndex\n ? { abilities: T['za'], conditions: T['zc'] }\n : never;\n\nexport type RuleOf<T extends AnyRuleIndex> =\n Rule<Generics<T>['abilities'], Generics<T>['conditions']>;\nexport type RawRuleOf<T extends AnyRuleIndex> =\n RawRuleFrom<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport type RuleIndexOptionsOf<T extends AnyRuleIndex> =\n RuleIndexOptions<Generics<T>['abilities'], Generics<T>['conditions']>;\n\nexport interface UpdateEvent<T extends AnyRuleIndex> {\n rules: RawRuleOf<T>[]\n}\nexport type EventHandler<Event> = (event: Event) => void;\n\nexport type Events<T extends AnyRuleIndex, Event extends {} = {}> = {\n [K in keyof EventsMap<T, Event>]: EventHandler<EventsMap<T, Event>[K]>[]\n};\n\ninterface EventsMap<T extends AnyRuleIndex, Event extends {} = {}> {\n update: UpdateEvent<T> & Event\n updated: UpdateEvent<T> & Event\n}\n\ninterface IndexTree<A extends Abilities, C> {\n [subject: string]: {\n [action: string]: {\n [priority: number]: Rule<A, C>\n }\n }\n}\n\ntype RuleIterator<A extends Abilities, C> = (rule: RawRuleFrom<A, C>, index: number) => void;\n\nexport type Unsubscribe = () => void;\n\nexport class RuleIndex<A extends Abilities, Conditions, BaseEvent extends {} = {}> {\n private _hasPerFieldRules: boolean = false;\n private _mergedRules: Record<string, Rule<A, Conditions>[]> = Object.create(null);\n private _events: Events<this, BaseEvent> = Object.create(null);\n private _indexedRules: IndexTree<A, Conditions> = Object.create(null);\n private _rules: this['rules'] = [];\n readonly rules!: RawRuleFrom<A, Conditions>[];\n readonly _ruleOptions!: RuleOptions<A, Conditions>;\n readonly detectSubjectType!: DetectSubjectType<Normalize<A>[1]>;\n /** @private hacky property to track Abilities type */\n readonly za!: A;\n /** @private hacky property to track Conditions type */\n readonly zc!: Conditions;\n\n constructor(\n rules: RawRuleFrom<A, Conditions>[] = [],\n options: RuleIndexOptions<A, Conditions> = {},\n ) {\n this._ruleOptions = {\n conditionsMatcher: options.conditionsMatcher,\n fieldMatcher: options.fieldMatcher,\n resolveAction: options.resolveAction || identity,\n };\n Object.defineProperty(this, 'detectSubjectType', {\n value: options.detectSubjectType || options.subjectName || detectSubjectType,\n });\n Object.defineProperty(this, 'rules', { get: () => this._rules });\n this.update(rules);\n }\n\n update(rules: RawRuleFrom<A, Conditions>[]): this {\n const event = {\n rules,\n ability: this,\n target: this,\n } as unknown as UpdateEvent<this> & BaseEvent;\n\n this._emit('update', event);\n this._mergedRules = Object.create(null);\n\n const analyser = new RulesAnalyzer<A, Conditions>(rules.length > 0);\n const indexedRules = this._buildIndexFor(rules, analyser._analyze);\n\n analyser._validate(this._ruleOptions);\n this._indexedRules = indexedRules;\n this._rules = rules;\n this._hasPerFieldRules = analyser._hasPerFieldRules;\n this._emit('updated', event);\n\n return this;\n }\n\n private _buildIndexFor(\n rawRules: RawRuleFrom<A, Conditions>[],\n iterator: RuleIterator<A, Conditions> = identity,\n ) {\n const indexedRules: IndexTree<A, Conditions> = Object.create(null);\n\n for (let i = 0; i < rawRules.length; i++) {\n iterator(rawRules[i], i);\n const rule = new Rule(rawRules[i], this._ruleOptions);\n const priority = rawRules.length - i - 1;\n const actions = wrapArray(rule.action);\n const subjects = wrapArray(rule.subject);\n\n for (let k = 0; k < subjects.length; k++) {\n const subject = this.detectSubjectType(subjects[k]);\n indexedRules[subject] = indexedRules[subject] || Object.create(null);\n\n for (let j = 0; j < actions.length; j++) {\n const action = actions[j];\n indexedRules[subject][action] = indexedRules[subject][action] || Object.create(null);\n indexedRules[subject][action][priority] = rule;\n }\n }\n }\n\n return indexedRules;\n }\n\n possibleRulesFor(...args: CanParameters<A, false>) {\n const [action, subject] = args;\n const subjectName = this.detectSubjectType(subject);\n const mergedRules = this._mergedRules;\n const key = `${subjectName}_${action}`;\n\n if (!mergedRules[key]) {\n mergedRules[key] = this._mergeRulesFor(action, subjectName);\n }\n\n return mergedRules[key];\n }\n\n private _mergeRulesFor(action: string, subjectName: string) {\n const subjects = subjectName === 'all' ? [subjectName] : [subjectName, 'all'];\n const mergedRules = subjects.reduce((rules, subjectType) => {\n const subjectRules = this._indexedRules[subjectType];\n\n if (!subjectRules) {\n return rules;\n }\n\n return Object.assign(rules, subjectRules[action], subjectRules.manage);\n }, []);\n\n // TODO: think whether there is a better way to prioritize rules\n // or convert sparse array to regular one\n return mergedRules.filter(Boolean);\n }\n\n rulesFor(...args: CanParameters<A>) {\n const [action, subject, field] = args;\n const rules: Rule<A, Conditions>[] = (this as any).possibleRulesFor(action, subject);\n\n if (field && typeof field !== 'string') {\n throw new Error('The 3rd, `field` parameter is expected to be a string. See https://stalniy.github.io/casl/en/api/casl-ability#can-of-pure-ability for details');\n }\n\n if (!this._hasPerFieldRules) {\n return rules;\n }\n\n return rules.filter(rule => rule.matchesField(field));\n }\n\n on<T extends keyof EventsMap<this, BaseEvent>>(\n event: T,\n handler: EventHandler<EventsMap<this, BaseEvent>[T]>,\n ): Unsubscribe {\n const events = this._events;\n let isAttached = true;\n\n if (!events[event]) {\n events[event] = [];\n }\n\n events[event].push(handler);\n\n return () => {\n if (isAttached) {\n const index = events[event].indexOf(handler);\n events[event].splice(index, 1);\n isAttached = false;\n }\n };\n }\n\n private _emit<T extends keyof EventsMap<this, BaseEvent>>(\n eventName: T,\n event: EventsMap<this, BaseEvent>[T],\n ) {\n const handlers = this._events[eventName];\n\n if (handlers) {\n handlers.slice(0).forEach(handler => handler(event));\n }\n }\n}\n","import { RuleIndex, RuleIndexOptions, RuleIndexOptionsOf, RawRuleOf } from './RuleIndex';\nimport { Abilities, CanParameters } from './types';\n\nexport type AbilityOptions<A extends Abilities, Conditions> = RuleIndexOptions<A, Conditions>;\nexport type AnyAbility = PureAbility<any, any>;\nexport type AbilityOptionsOf<T extends AnyAbility> = RuleIndexOptionsOf<T>;\nexport type AbilityClass<T extends AnyAbility> = new (\n rules?: RawRuleOf<T>[],\n options?: AbilityOptionsOf<T>\n) => T;\n\ninterface AbilityEvent<A extends Abilities = Abilities, Conditions = unknown> {\n /** @deprecated use \"target\" property instead */\n ability: this['target']\n target: PureAbility<A, Conditions>\n}\n\nexport class PureAbility<\n A extends Abilities = Abilities,\n Conditions = unknown,\n> extends RuleIndex<A, Conditions, AbilityEvent<A, Conditions>> {\n can(...args: CanParameters<A>): boolean {\n const rule = this.relevantRuleFor(...args);\n return !!rule && !rule.inverted;\n }\n\n relevantRuleFor(...args: CanParameters<A>) {\n const rules = this.rulesFor(...args);\n const subject = args[1];\n\n for (let i = 0; i < rules.length; i++) {\n if (rules[i].matchesConditions(subject)) {\n return rules[i];\n }\n }\n\n return null;\n }\n\n cannot(...args: CanParameters<A>): boolean {\n return !this.can(...args);\n }\n}\n","import {\n createQueryTester as sift,\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $elemMatch,\n $exists,\n} from 'sift';\nimport { ConditionsMatcher as Matcher } from '../types';\n\nconst defaultOperations = {\n $eq,\n $ne,\n $lt,\n $lte,\n $gt,\n $gte,\n $in,\n $nin,\n $all,\n $size,\n $regex,\n $elemMatch,\n $exists,\n};\n\ntype RegExpOptions<T> = { $regex: T, $options?: string };\ntype Primitive = Record<PropertyKey, any> | string | number | null | boolean | undefined;\nexport type MongoQueryOperators = {\n $eq?: any,\n $ne?: any,\n $lt?: string | number | Date,\n $lte?: string | number | Date,\n $gt?: string | number | Date,\n $gte?: string | number | Date,\n $in?: any[],\n $nin?: any[],\n $all?: any[],\n /** checks by array length */\n $size?: number,\n $regex?: RegExp | RegExpOptions<string> | RegExpOptions<RegExp>,\n /** checks the shape of array item */\n $elemMatch?: {\n [k in Exclude<keyof MongoQueryOperators, '$elemMatch'>]?: MongoQueryOperators[k]\n },\n /** checks that property exists */\n $exists?: boolean\n};\n\nexport type MongoQuery<AdditionalOperators = never> =\n Record<PropertyKey, MongoQueryOperators | Primitive | AdditionalOperators>;\nexport function buildMongoQueryMatcher<T extends object>(\n operations: Record<keyof T, any>,\n): Matcher<MongoQuery | T> {\n const options = { operations: { ...defaultOperations, ...operations } };\n return conditions => sift(conditions as any, options);\n}\nexport const mongoQueryMatcher = buildMongoQueryMatcher({});\n","import { FieldMatcher } from '../types';\n\nconst REGEXP_SPECIAL_CHARS = /[-/\\\\^$+?.()|[\\]{}]/g;\nconst REGEXP_ANY = /\\.?\\*+\\.?/g;\nconst REGEXP_STARS = /\\*+/;\nconst REGEXP_DOT = /\\./g;\n\nfunction detectRegexpPattern(match: string, index: number, string: string): string {\n const quantifier = string[0] === '*' || match[0] === '.' && match[match.length - 1] === '.'\n ? '+'\n : '*';\n const matcher = match.indexOf('**') === -1 ? '[^.]' : '.';\n const pattern = match.replace(REGEXP_DOT, '\\\\$&')\n .replace(REGEXP_STARS, matcher + quantifier);\n\n return index + match.length === string.length ? `(?:${pattern})?` : pattern;\n}\n\nfunction escapeRegexp(match: string, index: number, string: string): string {\n if (match === '.' && (string[index - 1] === '*' || string[index + 1] === '*')) {\n return match;\n }\n\n return `\\\\${match}`;\n}\n\nfunction createPattern(fields: string[]) {\n const patterns = fields.map(field => field\n .replace(REGEXP_SPECIAL_CHARS, escapeRegexp)\n .replace(REGEXP_ANY, detectRegexpPattern));\n const pattern = patterns.length > 1 ? `(?:${patterns.join('|')})` : patterns[0];\n\n return new RegExp(`^${pattern}$`);\n}\n\nexport const fieldPatternMatcher: FieldMatcher = (fields) => {\n let pattern: RegExp | null;\n\n return (field) => {\n if (typeof pattern === 'undefined') {\n pattern = fields.every(f => f.indexOf('*') === -1)\n ? null\n : createPattern(fields);\n }\n\n return pattern === null\n ? fields.indexOf(field) !== -1\n : pattern.test(field);\n };\n};\n","import { PureAbility, AbilityOptions } from './PureAbility';\nimport { AbilityTuple } from './types';\nimport { MongoQuery, mongoQueryMatcher } from './matchers/conditions';\nimport { RawRuleFrom } from './RawRule';\nimport { fieldPatternMatcher } from './matchers/field';\n\nexport class Ability<\n A extends AbilityTuple = AbilityTuple,\n C extends MongoQuery<any> = MongoQuery,\n> extends PureAbility<A, C> {\n constructor(rules?: RawRuleFrom<A, C>[], options?: AbilityOptions<A, C>) {\n super(rules, {\n conditionsMatcher: mongoQueryMatcher,\n fieldMatcher: fieldPatternMatcher,\n ...options,\n });\n }\n}\n\nexport type AnyMongoAbility = Ability<any, MongoQuery>;\n","import { Ability, AnyMongoAbility } from './Ability';\nimport { AnyAbility, AbilityOptionsOf, AbilityClass, PureAbility } from './PureAbility';\nimport { RawRuleOf, Generics } from './RuleIndex';\nimport {\n ExtractSubjectType as E,\n AbilityTuple,\n SubjectType,\n AbilityTypes,\n ToAbilityTypes,\n AbilityParameters,\n} from './types';\nimport { RawRule } from './RawRule';\n\nclass RuleBuilder<T extends RawRule<any, any>> {\n public rule!: T;\n\n constructor(rule: T) {\n this.rule = rule;\n }\n\n because(reason: string): this {\n this.rule.reason = reason;\n return this;\n }\n}\n\ntype CanFunction<T extends AbilityTypes, C, WithFields = true> = T extends AbilityTuple\n ? WithFields extends true\n // eslint-disable-next-line max-len\n ? (action: T[0] | T[0][], subject: E<T[1]> | E<T[1]>[], fields?: string | string[], conditions?: C) => 0\n : (action: T[0] | T[0][], subject: E<T[1]> | E<T[1]>[], conditions?: C) => 0\n : never;\n\nexport type BuilderCanParameters<T extends AnyAbility, WithFields extends boolean = false> =\n AbilityParameters<\n Generics<T>['abilities'],\n CanFunction<ToAbilityTypes<Generics<T>['abilities']>, Generics<T>['conditions'], WithFields>,\n (action: Generics<T>['abilities'] | Generics<T>['abilities'][]) => 0\n >;\n\nexport class AbilityBuilder<T extends AnyAbility = PureAbility> {\n public rules: RawRuleOf<T>[] = [];\n private _AbilityType!: AbilityClass<T>;\n\n constructor(AbilityType: AbilityClass<T> = PureAbility as AbilityClass<T>) {\n this._AbilityType = AbilityType;\n const self = this as any;\n self.can = self.can.bind(self);\n self.cannot = self.cannot.bind(self);\n self.build = self.build.bind(self);\n }\n\n can(...args: BuilderCanParameters<T>): RuleBuilder<RawRuleOf<T>>\n can(...args: BuilderCanParameters<T, true>): RuleBuilder<RawRuleOf<T>>\n can(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<RawRuleOf<T>> {\n const rule = { action } as RawRuleOf<T>;\n\n if (subject) {\n rule.subject = subject;\n\n if (Array.isArray(conditionsOrFields) || typeof conditionsOrFields === 'string') {\n rule.fields = conditionsOrFields;\n } else if (typeof conditionsOrFields !== 'undefined') {\n rule.conditions = conditionsOrFields;\n }\n\n if (typeof conditions !== 'undefined') {\n rule.conditions = conditions;\n }\n }\n\n this.rules.push(rule);\n\n return new RuleBuilder(rule);\n }\n\n cannot(...args: BuilderCanParameters<T>): RuleBuilder<RawRuleOf<T>>\n cannot(...args: BuilderCanParameters<T, true>): RuleBuilder<RawRuleOf<T>>\n cannot(\n action: string | string[],\n subject?: SubjectType | SubjectType[],\n conditionsOrFields?: string | string[] | Generics<T>['conditions'],\n conditions?: Generics<T>['conditions'],\n ): RuleBuilder<RawRuleOf<T>> {\n const builder = (this as any).can(action, subject, conditionsOrFields, conditions);\n builder.rule.inverted = true;\n return builder;\n }\n\n build(options?: AbilityOptionsOf<T>): T {\n return new this._AbilityType(this.rules, options);\n }\n}\n\ntype AsyncDSL<T extends AnyMongoAbility> = (\n can: AbilityBuilder<T>['can'],\n cannot: AbilityBuilder<T>['cannot']\n) => Promise<void>;\ntype DSL<T extends AnyMongoAbility> = (...args: Parameters<AsyncDSL<T>>) => void;\n\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n dsl: AsyncDSL<T>\n): Promise<T>;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T>,\n dsl: AsyncDSL<T>\n): Promise<T>;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n dsl: DSL<T>\n): T;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T>,\n dsl: DSL<T>\n): T;\nexport function defineAbility<T extends AnyMongoAbility = Ability>(\n params: AbilityOptionsOf<T> | DSL<T> | AsyncDSL<T>,\n dsl?: DSL<T> | AsyncDSL<T>,\n): T | Promise<T> {\n let options: AbilityOptionsOf<T>;\n let define: DSL<T> | AsyncDSL<T>;\n\n if (typeof params === 'function') {\n define = params;\n options = {};\n } else if (typeof dsl === 'function') {\n options = params;\n define = dsl;\n } else {\n throw new Error('`defineAbility` expects to receive either options and dsl function or only dsl function');\n }\n\n const builder = new AbilityBuilder<T>(Ability as AbilityClass<T>);\n const result = define(builder.can, builder.cannot);\n\n return result && typeof result.then === 'function'\n ? result.then(() => builder.build(options))\n : builder.build(options);\n}\n","import { AnyAbility } from './PureAbility';\nimport { Normalize } from './types';\nimport { Generics } from './RuleIndex';\n\nexport type GetErrorMessage = (error: ForbiddenError<AnyAbility>) => string;\nexport const getDefaultErrorMessage: GetErrorMessage = error => `Cannot execute \"${error.action}\" on \"${error.subjectType}\"`;\n\nconst NativeError = function NError(this: Error, message: string) {\n this.message = message;\n} as unknown as new (message: string) => Error;\n\nNativeError.prototype = Object.create(Error.prototype);\n\nexport class ForbiddenError<T extends AnyAbility> extends NativeError {\n public readonly ability: T;\n public action!: Normalize<Generics<T>['abilities']>[0];\n public subject!: Generics<T>['abilities'][1];\n public field?: string;\n public subjectType!: string;\n\n static _defaultErrorMessage = getDefaultErrorMessage;\n\n static setDefaultMessage(messageOrFn: string | GetErrorMessage) {\n this._defaultErrorMessage = typeof messageOrFn === 'string' ? () => messageOrFn : messageOrFn;\n }\n\n static from<U extends AnyAbility>(ability: U) {\n return new this<U>(ability);\n }\n\n private constructor(ability: T) {\n super('');\n this.ability = ability;\n\n if (typeof Error.captureStackTrace === 'function') {\n this.name = 'ForbiddenError';\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n setMessage(message: string) {\n this.message = message;\n return this;\n }\n\n throwUnlessCan(...args: Parameters<T['can']>) {\n const rule = this.ability.relevantRuleFor(...args);\n\n if (rule && !rule.inverted) {\n return;\n }\n\n this.action = args[0];\n this.subject = args[1];\n this.subjectType = this.ability.detectSubjectType(args[1]);\n this.field = args[2];\n\n const reason = rule ? rule.reason : '';\n // eslint-disable-next-line no-underscore-dangle\n this.message = this.message || reason || (this.constructor as any)._defaultErrorMessage(this);\n throw this; // eslint-disable-line\n }\n}\n"],"names":["wrapArray","value","Array","isArray","TYPE_FIELD","setSubjectType","type","object","hasOwnProperty","Object","defineProperty","Error","detectSubjectType","subject","Type","constructor","modelName","name","expandActions","aliasMap","rawActions","actions","i","length","action","concat","assertAliasMap","manage","keys","forEach","alias","hasError","indexOf","identity","x","createAliasResolver","process","env","NODE_ENV","Rule","rule","options","_matchConditions","_matchField","resolveAction","inverted","conditions","reason","fields","undefined","console","warn","conditionsMatcher","fieldMatcher","matchesConditions","matchesField","field","RulesAnalyzer","hasRules","_isAllInverted","_hasPerFieldRules","_hasRuleWithEmptyFields","_analyze","bind","_validate","ruleOptions","RuleIndex","rules","_mergedRules","create","_events","_indexedRules","_rules","_ruleOptions","subjectName","get","update","event","ability","target","_emit","analyser","indexedRules","_buildIndexFor","rawRules","iterator","priority","subjects","k","j","possibleRulesFor","args","mergedRules","key","_mergeRulesFor","reduce","subjectType","subjectRules","assign","filter","Boolean","rulesFor","on","handler","events","isAttached","push","index","splice","eventName","handlers","slice","PureAbility","can","relevantRuleFor","cannot","defaultOperations","$eq","$ne","$lt","$lte","$gt","$gte","$in","$nin","$all","$size","$regex","$elemMatch","$exists","buildMongoQueryMatcher","operations","sift","mongoQueryMatcher","REGEXP_SPECIAL_CHARS","REGEXP_ANY","REGEXP_STARS","REGEXP_DOT","detectRegexpPattern","match","string","quantifier","matcher","pattern","replace","escapeRegexp","createPattern","patterns","map","join","RegExp","fieldPatternMatcher","every","f","test","Ability","RuleBuilder","because","AbilityBuilder","AbilityType","_AbilityType","self","build","conditionsOrFields","builder","defineAbility","params","dsl","define","result","then","getDefaultErrorMessage","error","NativeError","NError","message","prototype","ForbiddenError","setDefaultMessage","messageOrFn","_defaultErrorMessage","from","captureStackTrace","setMessage","throwUnlessCan"],"mappings":"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"} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
8
-11.11%5
-16.67%343533
-16.18%40
-13.04%557
-48.66%