UNPKG

@casl/ability

Version:

CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access

280 lines (265 loc) 10.3 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const t = require("./utils-DKsJWNoq.cjs"); let s = require("@ucast/mongo2js"); var i = class { constructor(s, i, e = 0) { !function(t, s) { if (Array.isArray(t.fields) && !t.fields.length) throw new Error("The `rawRule.fields` array cannot be empty. https://bit.ly/390miLa"); if (t.fields && !s.fieldMatcher) throw new Error('Cannot restrict access by fields without a "fieldMatcher" option'); if (t.conditions && !s.conditionsMatcher) throw new Error('Cannot restrict access by conditions without a "conditionsMatcher" option. Please, provide a "conditionsMatcher" function to your Ability class or use "createMongoAbility" instead.'); }(s, i), this.action = i.resolveAction(s.action), this.subject = s.subject, this.inverted = !!s.inverted, this.conditions = s.conditions, this.reason = s.reason, this.origin = s, this.fields = s.fields ? t.wrapArray(s.fields) : void 0, this.priority = e, this.t = i; } i() { return this.conditions && !this.o && (this.o = this.t.conditionsMatcher(this.conditions)), this.o; } get ast() { const t = this.i(); return t ? t.ast : void 0; } matchesConditions(s) { if (!this.conditions) return !0; if (!s || t.isSubjectType(s)) { if (!this.inverted) return !0; const t = this.i(); return !!t && (!0 === t.matchesAll || !!t.ast && (("and" === (i = t.ast).operator || "AND" === i.operator) && Array.isArray(i.value) && 0 === i.value.length)); } var i; const e = this.i(); return !!e && e(s); } matchesField(t) { return !this.fields || (t ? (this.h || (this.h = this.t.fieldMatcher(this.fields)), !!this.h && this.h(t)) : !this.inverted); } }; const e = () => ({ rules: [], merged: !1 }), r = () => new Map; var n = class { constructor(s = [], i = {}) { this.u = !1, this.l = new Map, this.p = { conditionsMatcher: i.conditionsMatcher, fieldMatcher: i.fieldMatcher, resolveAction: i.resolveAction || t.identity }, this.$ = i.anyAction || "manage", this.v = i.anySubjectType || "all", this.m = s, this.M = !!i.detectSubjectType, this.A = i.detectSubjectType || t.detectSubjectType, this.j(s); } get rules() { return this.m; } detectSubjectType(s) { return t.isSubjectType(s) ? s : s ? this.A(s) : this.v; } update(t) { const s = { rules: t, ability: this, target: this }; return this.F("update", s), this.u = !1, this.m = t, this.j(t), this.F("updated", s), this; } j(s) { const n = new Map; let o; for (let h = s.length - 1; h >= 0; h--) { const c = s.length - h - 1, a = new i(s[h], this.p, c), u = t.wrapArray(a.action), l = t.wrapArray(a.subject || this.v); !this.u && a.fields && (this.u = !0); for (let s = 0; s < l.length; s++) { const i = t.getOrDefault(n, l[s], r); void 0 === o && (o = typeof l[s]), typeof l[s] !== o && "mixed" !== o && (o = "mixed"); for (let s = 0; s < u.length; s++) t.getOrDefault(i, u[s], e).rules.push(a); } } if (this.l = n, "mixed" !== o && !this.M) { const s = t.DETECT_SUBJECT_TYPE_STRATEGY[o] || t.DETECT_SUBJECT_TYPE_STRATEGY.string; this.A = s; } } possibleRulesFor(s, i = this.v) { if (!t.isSubjectType(i)) throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter'); const e = this.l.get(i), r = e?.get(s); if (r?.merged) return r.rules; const n = s !== this.$ && e?.has(this.$) ? Object.freeze(e.get(this.$).rules) : void 0; let o = t.mergePrioritized(r?.rules, n); return i !== this.v && (o = t.mergePrioritized(o, this.possibleRulesFor(s, this.v))), r && (r.rules = Object.freeze(o), r.merged = !0), o; } rulesFor(s, i, e) { const r = this.possibleRulesFor(s, i); if (e && "string" != typeof e) throw new Error("The 3rd, `field` parameter is expected to be a string. See https://casl.js.org/v6/en/api/casl-ability#can-of-ability for details"); return this.u ? t.filterWithLazyAllocation(r, t => t.matchesField(e)) : r; } actionsFor(s) { if (!t.isSubjectType(s)) throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter'); const i = new Set, e = this.l.get(s); e && Array.from(e.keys()).forEach(t => i.add(t)); const r = s !== this.v ? this.l.get(this.v) : void 0; return r && Array.from(r.keys()).forEach(t => i.add(t)), Array.from(i); } on(t, s) { this.R = this.R || new Map; const i = this.R, e = function(t, s) { const i = { value: t, prev: s, next: null }; return s && (s.next = i), i; }(s, i.get(t) || null); return i.set(t, e), () => { const s = i.get(t); e.next || e.prev || s !== e ? e === s && i.set(t, e.prev) : i.delete(t), function(t) { t.next && (t.next.prev = t.prev), t.prev && (t.prev.next = t.next), t.next = t.prev = null; }(e); }; } F(t, s) { if (!this.R) return; let i = this.R.get(t) || null; const e = []; for (;null !== i; ) e.push(i.value), i = i.prev; for (let t = 0; t < e.length; t++) e[t](s); } }, o = class extends n { can(t, s, i) { const e = this.relevantRuleFor(t, s, i); return !!e && !e.inverted; } relevantRuleFor(t, s, i) { const e = this.detectSubjectType(s), r = this.rulesFor(t, e, i); for (let t = 0, i = r.length; t < i; t++) if (r[t].matchesConditions(s)) return r[t]; return null; } cannot(t, s, i) { return !this.can(t, s, i); } }; const h = { $eq: s.$eq, $ne: s.$ne, $lt: s.$lt, $lte: s.$lte, $gt: s.$gt, $gte: s.$gte, $in: s.$in, $nin: s.$nin, $all: s.$all, $size: s.$size, $regex: s.$regex, $options: s.$options, $elemMatch: s.$elemMatch, $exists: s.$exists }, c = { eq: s.eq, ne: s.ne, lt: s.lt, lte: s.lte, gt: s.gt, gte: s.gte, in: s.within, nin: s.nin, all: s.all, size: s.size, regex: s.regex, elemMatch: s.elemMatch, exists: s.exists, and: s.and }, a = (0, s.createFactory)(h, c), u = /[-/\\^$+?.()|[\]{}]/g, l = /\.?\*+\.?/g, f = /\*+/, p = /\./g; function d(t, s, i) { const e = "*" === i[0] || "." === t[0] && "." === t[t.length - 1] ? "+" : "*", r = -1 === t.indexOf("**") ? "[^.]" : ".", n = t.replace(p, "\\$&").replace(f, r + e); return s + t.length === i.length ? `(?:${n})?` : n; } function y(t, s, i) { return "." !== t || "*" !== i[s - 1] && "*" !== i[s + 1] ? `\\${t}` : t; } const w = t => { let s; return i => (void 0 === s && (s = t.every(t => -1 === t.indexOf("*")) ? null : function(t) { const s = t.map(t => t.replace(u, y).replace(l, d)), i = s.length > 1 ? `(?:${s.join("|")})` : s[0]; return new RegExp(`^${i}$`); }(t)), null === s ? -1 !== t.indexOf(i) : s.test(i)); }; function x(t = [], s = {}) { return new o(t, { conditionsMatcher: a, fieldMatcher: w, ...s }); } var g = class { constructor(t) { this.C = t; } because(t) { return this.C.reason = t, this; } }, $ = class { constructor(t) { this.rules = [], this.q = t, this.can = (t, s, i, e) => this.O(t, s, i, e, !1), this.cannot = (t, s, i, e) => this.O(t, s, i, e, !0), this.build = t => { return void 0 !== (s = this.q).prototype && "function" == typeof s.prototype.possibleRulesFor ? new this.q(this.rules, t) : this.q(this.rules, t); var s; }; } O(t, s, i, e, r) { const n = { action: t }; return r && (n.inverted = r), s && (n.subject = s, Array.isArray(i) || "string" == typeof i ? n.fields = i : void 0 !== i && (n.conditions = i), void 0 !== e && (n.conditions = e)), this.rules.push(n), new g(n); } }; const b = function(t) { this.message = t; }; b.prototype = Object.create(Error.prototype); var v = class extends b { static setDefaultMessage(t) { this.S = "string" == typeof t ? () => t : t; } static from(t) { return new this(t); } constructor(t) { super(""), this.ability = t, "function" == typeof Error.captureStackTrace && (this.name = "ForbiddenError", Error.captureStackTrace(this, this.constructor)); } setMessage(t) { return this.message = t, this; } throwUnlessCan(t, s, i) { const e = this.unlessCan(t, s, i); if (e) throw e; } unlessCan(s, i, e) { const r = this.ability.relevantRuleFor(s, i, e); if (r && !r.inverted) return; this.action = s, this.subject = i, this.subjectType = t.getSubjectTypeName(this.ability.detectSubjectType(i)), this.field = e; const n = r ? r.reason : ""; return this.message = this.message || n || this.constructor.S(this), this; } }; v.S = t => `Cannot execute "${t.action}" on "${t.subjectType}"`, exports.Ability = o, exports.AbilityBuilder = $, exports.ForbiddenError = v, exports.buildMongoQueryMatcher = (t, i, e) => (0, s.createFactory)({ ...h, ...t }, { ...c, ...i }, e), exports.createAliasResolver = t.createAliasResolver, exports.createMongoAbility = x, exports.defineAbility = function(t, s) { const i = new $(x), e = t(i.can, i.cannot); return e && "function" == typeof e.then ? e.then(() => i.build(s)) : i.build(s); }, exports.detectSubjectType = t.detectSubjectType, exports.fieldPatternMatcher = w, exports.mongoQueryMatcher = a, exports.subject = t.setSubjectType, exports.wrapArray = t.wrapArray; //# sourceMappingURL=index.cjs.map