3 lines
8.9 KiB
JavaScript
3 lines
8.9 KiB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:true});var t=require("@ucast/mongo2js");function e(t){return Array.isArray(t)?t:[t]}const s=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);const i="__caslSubjectType__";function r(t,e){if(e)if(!s(e,i))Object.defineProperty(e,i,{value:t});else if(t!==e[i])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[i]}`);return e}const n=t=>{const e=typeof t;return"string"===e||"function"===e};const o=t=>t.modelName||t.name;const c=t=>"string"===typeof t?t:o(t);function u(t){if(s(t,i))return t[i];return o(t.constructor)}function h(t,i,r){let n=e(i);let o=0;while(o<n.length){const e=n[o++];if(s(t,e))n=r(n,t[e])}return n}function l(t,e){if("string"===typeof e&&-1!==t.indexOf(e))return e;for(let s=0;s<e.length;s++)if(-1!==t.indexOf(e[s]))return e[s];return null}const a=(t,e)=>t.concat(e);function f(t,e){if(e in t)throw new Error(`Cannot use "${e}" as an alias because it's reserved action.`);const s=Object.keys(t);const i=(t,s)=>{const i=l(t,s);if(i)throw new Error(`Detected cycle ${i} -> ${t.join(", ")}`);const r="string"===typeof s&&s===e||-1!==t.indexOf(e)||Array.isArray(s)&&-1!==s.indexOf(e);if(r)throw new Error(`Cannot make an alias to "${e}" because this is reserved action`);return t.concat(s)};for(let e=0;e<s.length;e++)h(t,s[e],i)}function d(t,e){if(!e||false!==e.skipValidate)f(t,e&&e.anyAction||"manage");return e=>h(t,e,a)}function p(t,e,s){for(let i=s;i<e.length;i++)t.push(e[i])}function y(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let s=0;let i=0;const r=[];while(s<t.length&&i<e.length)if(t[s].priority<e[i].priority){r.push(t[s]);s++}else{r.push(e[i]);i++}p(r,t,s);p(r,e,i);return r}function b(t,e,s){let i=t.get(e);if(!i){i=s();t.set(e,i)}return i}const w=t=>t;function g(t,e){if(Array.isArray(t.fields)&&!t.fields.length)throw new Error("`rawRule.fields` cannot be an empty array. https://bit.ly/390miLa");if(t.fields&&!e.fieldMatcher)throw new Error('You need to pass "fieldMatcher" option in order to restrict access by fields');if(t.conditions&&!e.conditionsMatcher)throw new Error('You need to pass "conditionsMatcher" option in order to restrict access by conditions')}class x{constructor(t,s,i=0){g(t,s);this.action=s.resolveAction(t.action);this.subject=t.subject;this.inverted=!!t.inverted;this.conditions=t.conditions;this.reason=t.reason;this.origin=t;this.fields=t.fields?e(t.fields):void 0;this.priority=i;this.t=s}i(){if(this.conditions&&!this.o)this.o=this.t.conditionsMatcher(this.conditions);return this.o}get ast(){const t=this.i();return t?t.ast:void 0}matchesConditions(t){if(!this.conditions)return true;if(!t||n(t))return!this.inverted;const e=this.i();return e(t)}matchesField(t){if(!this.fields)return true;if(!t)return!this.inverted;if(this.fields&&!this.u)this.u=this.t.fieldMatcher(this.fields);return this.u(t)}}function $(t,e){const s={value:t,prev:e,next:null};if(e)e.next=s;return s}function A(t){if(t.next)t.next.prev=t.prev;if(t.prev)t.prev.next=t.next;t.next=t.prev=null}const M=t=>({value:t.value,prev:t.prev,next:t.next});const j=()=>({rules:[],merged:false});const E=()=>new Map;class v{constructor(t=[],e={}){this.h=false;this.l={conditionsMatcher:e.conditionsMatcher,fieldMatcher:e.fieldMatcher,resolveAction:e.resolveAction||w};this.p=e.anyAction||"manage";this.g=e.anySubjectType||"all";this.$=e.detectSubjectType||u;this.A=t;this.M=this.j(t)}get rules(){return this.A}detectSubjectType(t){if(n(t))return t;if(!t)return this.g;return this.$(t)}update(t){const e={rules:t,ability:this,target:this};this.v("update",e);this.A=t;this.M=this.j(t);this.v("updated",e);return this}j(t){const s=new Map;for(let i=t.length-1;i>=0;i--){const r=t.length-i-1;const n=new x(t[i],this.l,r);const o=e(n.action);const c=e(n.subject||this.g);if(!this.h&&n.fields)this.h=true;for(let t=0;t<c.length;t++){const e=b(s,c[t],E);for(let t=0;t<o.length;t++)b(e,o[t],j).rules.push(n)}}return s}possibleRulesFor(t,e=this.g){if(!n(e))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');const s=b(this.M,e,E);const i=b(s,t,j);if(i.merged)return i.rules;const r=t!==this.p&&s.has(this.p)?s.get(this.p).rules:void 0;let o=y(i.rules,r);if(e!==this.g)o=y(o,this.possibleRulesFor(t,this.g));i.rules=o;i.merged=true;return o}rulesFor(t,e,s){const i=this.possibleRulesFor(t,e);if(s&&"string"!==typeof s)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.h)return i;return i.filter((t=>t.matchesField(s)))}actionsFor(t){if(!n(t))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');const e=new Set;const s=this.M.get(t);if(s)Array.from(s.keys()).forEach((t=>e.add(t)));const i=t!==this.g?this.M.get(this.g):void 0;if(i)Array.from(i.keys()).forEach((t=>e.add(t)));return Array.from(e)}on(t,e){this.m=this.m||new Map;const s=this.m;const i=s.get(t)||null;const r=$(e,i);s.set(t,r);return()=>{const e=s.get(t);if(!r.next&&!r.prev&&e===r)s.delete(t);else if(r===e)s.set(t,r.prev);A(r)}}v(t,e){if(!this.m)return;let s=this.m.get(t)||null;while(null!==s){const t=s.prev?M(s.prev):null;s.value(e);s=t}}}class PureAbility extends v{can(t,e,s){const i=this.relevantRuleFor(t,e,s);return!!i&&!i.inverted}relevantRuleFor(t,e,s){const i=this.detectSubjectType(e);const r=this.rulesFor(t,i,s);for(let t=0,s=r.length;t<s;t++)if(r[t].matchesConditions(e))return r[t];return null}cannot(t,e,s){return!this.can(t,e,s)}}const m={$eq:t.$eq,$ne:t.$ne,$lt:t.$lt,$lte:t.$lte,$gt:t.$gt,$gte:t.$gte,$in:t.$in,$nin:t.$nin,$all:t.$all,$size:t.$size,$regex:t.$regex,$options:t.$options,$elemMatch:t.$elemMatch,$exists:t.$exists};const _={eq:t.eq,ne:t.ne,lt:t.lt,lte:t.lte,gt:t.gt,gte:t.gte,in:t.within,nin:t.nin,all:t.all,size:t.size,regex:t.regex,elemMatch:t.elemMatch,exists:t.exists,and:t.and};const F=(e,s,i)=>t.createFactory(Object.assign({},m,e),Object.assign({},_,s),i);const O=t.createFactory(m,_);const C=/[-/\\^$+?.()|[\]{}]/g;const R=/\.?\*+\.?/g;const P=/\*+/;const S=/\./g;function T(t,e,s){const i="*"===s[0]||"."===t[0]&&"."===t[t.length-1]?"+":"*";const r=-1===t.indexOf("**")?"[^.]":".";const n=t.replace(S,"\\$&").replace(P,r+i);return e+t.length===s.length?`(?:${n})?`:n}function q(t,e,s){if("."===t&&("*"===s[e-1]||"*"===s[e+1]))return t;return`\\${t}`}function B(t){const e=t.map((t=>t.replace(C,q).replace(R,T)));const s=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${s}$`)}const z=t=>{let e;return s=>{if("undefined"===typeof e)e=t.every((t=>-1===t.indexOf("*")))?null:B(t);return null===e?-1!==t.indexOf(s):e.test(s)}};class Ability extends PureAbility{constructor(t=[],e={}){super(t,Object.assign({conditionsMatcher:O,fieldMatcher:z},e))}}function createMongoAbility(t=[],e={}){return new PureAbility(t,Object.assign({conditionsMatcher:O,fieldMatcher:z},e))}function isAbilityClass(t){return"function"===typeof t.prototype.possibleRulesFor}class D{constructor(t){this._=t}because(t){this._.reason=t;return this}}class AbilityBuilder{constructor(t){this.rules=[];this.F=t;this.can=(t,e,s,i)=>this.O(t,e,s,i,false);this.cannot=(t,e,s,i)=>this.O(t,e,s,i,true);this.build=t=>isAbilityClass(this.F)?new this.F(this.rules,t):this.F(this.rules,t)}O(t,e,s,i,r){const n={action:t};if(r)n.inverted=r;if(e){n.subject=e;if(Array.isArray(s)||"string"===typeof s)n.fields=s;else if("undefined"!==typeof s)n.conditions=s;if("undefined"!==typeof i)n.conditions=i}this.rules.push(n);return new D(n)}}function defineAbility(t,e){const s=new AbilityBuilder(createMongoAbility);const i=t(s.can,s.cannot);if(i&&"function"===typeof i.then)return i.then((()=>s.build(e)));return s.build(e)}const Y=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`;const k=function t(e){this.message=e};k.prototype=Object.create(Error.prototype);class ForbiddenError extends k{static setDefaultMessage(t){this.C="string"===typeof t?()=>t:t}static from(t){return new this(t)}constructor(t){super("");this.ability=t;if("function"===typeof Error.captureStackTrace){this.name="ForbiddenError";Error.captureStackTrace(this,this.constructor)}}setMessage(t){this.message=t;return this}throwUnlessCan(t,e,s){const i=this.unlessCan(t,e,s);if(i)throw i}unlessCan(t,e,s){const i=this.ability.relevantRuleFor(t,e,s);if(i&&!i.inverted)return;this.action=t;this.subject=e;this.subjectType=c(this.ability.detectSubjectType(e));this.field=s;const r=i?i.reason:"";this.message=this.message||r||this.constructor.C(this);return this}}ForbiddenError.C=Y;var I=Object.freeze({__proto__:null});exports.Ability=Ability;exports.AbilityBuilder=AbilityBuilder;exports.ForbiddenError=ForbiddenError;exports.PureAbility=PureAbility;exports.buildMongoQueryMatcher=F;exports.createAliasResolver=d;exports.createMongoAbility=createMongoAbility;exports.defineAbility=defineAbility;exports.detectSubjectType=u;exports.fieldPatternMatcher=z;exports.getDefaultErrorMessage=Y;exports.hkt=I;exports.mongoQueryMatcher=O;exports.subject=r;exports.wrapArray=e;
|
|
//# sourceMappingURL=index.js.map
|