@liquisio/wix-access 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -72,15 +72,19 @@ the **release** rather than a request.
72
72
 
73
73
  ## Using it
74
74
 
75
- **Web methods** — you write the export line, the package decides the call.
75
+ **Web methods** — you write the export line, the policy decides the gate.
76
76
 
77
- Wix only ever hands page code a web method written in exactly this form, so the
78
- `webMethod` call and the permission literal have to be yours:
77
+ Wix treats a web method in two separate ways, and both matter.
78
+
79
+ *Whether an export becomes a web method at all* is decided at build time, by reading the
80
+ source. Only this exact form is recognised, so the `webMethod` call and the permission
81
+ literal have to be yours:
79
82
 
80
83
  ```js
81
84
  // backend/api.web.js
82
85
  import { webMethod, Permissions } from 'wix-web-module'
83
- import { guard } from 'backend/access'
86
+ import { guard, applyGates } from 'backend/access'
87
+ import policy from 'public/access-policy'
84
88
  import { cancelBooking as _cancelBooking, getBooking } from 'backend/booking-service'
85
89
 
86
90
  const _cancel = guard(
@@ -96,21 +100,37 @@ const _cancel = guard(
96
100
  )
97
101
 
98
102
  export const cancelBooking = webMethod(Permissions.SiteMember, async (...args) => await _cancel(...args))
103
+
104
+ // The policy is the authority. One line, at the end of the file.
105
+ applyGates({ cancelBooking }, policy)
99
106
  ```
100
107
 
101
- Three rules, and breaking any of them makes the export arrive in the browser as
102
- `undefined` rather than failing loudly:
108
+ Break any of these three and the export arrives in the browser as `undefined` rather than
109
+ failing loudly:
103
110
 
104
111
  - the `webMethod(...)` call and the `export const` are one statement;
105
- - the permission is written out as `Permissions.LEVEL`, never computed, aliased
106
- or bracketed;
107
- - the second argument is a function written in place. Passing `_cancel` straight
108
- in does not work; calling it from inside the arrow does.
112
+ - the permission is written out as `Permissions.LEVEL`, never computed, aliased or bracketed;
113
+ - the second argument is a function written in place. Passing `_cancel` straight in does not
114
+ work; calling it from inside the arrow does.
115
+
116
+ *Which level is enforced* is read from the method's `permission` property when the request
117
+ arrives. That is what `applyGates` sets, from `policy.api`, so the manifest wins over the
118
+ literal you typed and cannot drift from it. A method missing from the policy throws there,
119
+ rather than quietly keeping whatever the literal said.
120
+
121
+ Three independent things now have to agree before a caller gets through, and each is checked
122
+ somewhere different:
109
123
 
110
- Because you type the gate, it can drift from the policy. Two things stop that.
111
- `guard` re-checks the declared level at request time, so a method the policy
112
- calls `Admin` refuses a caller without the Admin role even if the export says
113
- `Anyone`. And `assertGates` reads the file and compares:
124
+ | Layer | Set by | Checked by |
125
+ | --- | --- | --- |
126
+ | the platform gate | `applyGates`, from the policy | Wix, at request time |
127
+ | the literal you typed | you | `assertGates` in a test |
128
+ | the caller's level and ability | the policy | `guard`, in code, per request |
129
+
130
+ `guard` re-checks the declared level itself, so a method the policy calls `Admin` refuses a
131
+ caller without the Admin role even if `applyGates` was never called. And `assertGates` reads
132
+ the file and reports any literal that disagrees with the policy, plus the unreachable export
133
+ shapes above:
114
134
 
115
135
  ```js
116
136
  // tests/gates.test.js
@@ -121,13 +141,9 @@ import policy from '../src/public/access-policy.js'
121
141
  assertGates(readFileSync('src/backend/api.web.js', 'utf8'), policy, { complete: true })
122
142
  ```
123
143
 
124
- It also flags the unreachable export shapes above, which is the failure worth
125
- catching early: a mis-typed gate is a bug, but a dropped export is a call site
126
- that throws "is not a function" with nothing to point at.
127
-
128
- A method missing from `policy.api` throws at construction, so an undocumented
129
- gate fails the build. `gateFor(name)` returns the level to type, for a test —
130
- never at the call site, where it would be a computed permission.
144
+ A method missing from `policy.api` throws when `guard` is constructed, so an undocumented gate
145
+ fails the build. `gateFor(name)` returns the level, for a test — never at the call site, where
146
+ it would be a computed permission and the export would vanish.
131
147
 
132
148
  **Data** — elevation and authorization together, so neither is used without the other.
133
149
 
@@ -140,6 +156,40 @@ const result = await db.get('Bookings', id, { principal }) // opaque
140
156
  await db.insert('Bookings', row, { principal, action: 'create' }) // stamps the owner field
141
157
  ```
142
158
 
159
+ **Creating a row for someone else.** An admin taking a phone booking, staff booking a
160
+ walk-in, a guest matched to an account by email. Wix cannot do this with `_owner` — an
161
+ elevated write stores `null`, and setting `_owner` explicitly does not stick — so the
162
+ gateway does it with the declared fields:
163
+
164
+ ```js
165
+ // policy.collections
166
+ Bookings: { resource: 'Booking', owner: 'customerId', actor: 'createdBy', tenant: 'vendor' }
167
+
168
+ // policy.rules — who may put a row in another member's name. `manage` already covers it.
169
+ { subject: 'vendorStaff', actions: 'assignOwner', resource: 'Booking',
170
+ where: { vendor: { $in: '$principal.domain.vendorIds' } } }
171
+ ```
172
+
173
+ ```js
174
+ // staff or admin, checked against assignOwner
175
+ await db.insert('Bookings', row, { principal, onBehalfOf: customerMemberId })
176
+
177
+ // the server decided the owner itself; the caller (a visitor) holds no assignOwner
178
+ await db.insert('Bookings', row, { principal, onBehalfOf: matchedMemberId, system: true })
179
+
180
+ // re-own an existing row, or detach it with null
181
+ await db.transfer('Bookings', bookingId, rightMemberId, { principal })
182
+ ```
183
+
184
+ - The owner is **never read from the record.** It is the caller's member id (`null` for a
185
+ visitor) unless `onBehalfOf` says otherwise, and only server code can pass that option.
186
+ - `actor` records who really created the row. It is stamped on insert and never changes.
187
+ - `update` keeps both fields as stored and refuses `onBehalfOf`; ownership moves only by
188
+ `transfer`, which checks `assignOwner` against the row before and after the move.
189
+ - Every delegated insert and every transfer reaches the `audit` sink as `access.onBehalf`
190
+ or `access.transfer`, `system` ones included. An audit sink that throws does not fail
191
+ the write — it goes to `onError('audit', error)` instead.
192
+
143
193
  **Page code** — the same rules, so the UI agrees with the server.
144
194
 
145
195
  ```js
@@ -172,6 +222,18 @@ $w.onReady(async () => {
172
222
 
173
223
  Each is measured, and each will bite otherwise.
174
224
 
225
+ - **The platform gate runs BEFORE any of your code.** Wix reads the method's
226
+ `permission` and refuses first; your handler, and therefore `guard`, never run
227
+ for a caller who fails it. Measured: a method gated `Admin` returned the
228
+ platform's opaque `NotAuthorizedError` to a plain member, not the package's
229
+ refusal envelope. So `guard`'s own level check is a **second** line, not the
230
+ first — it matters when the platform gate is looser than the policy, or when
231
+ `applyGates` was never called.
232
+ - **Which means level failures are opaque and ownership failures are not.** A
233
+ caller refused by the platform gets a generic error with no reason. A caller
234
+ who passes the gate but fails an ownership or ability check reaches your code
235
+ and gets a refusal envelope with a code. That is the right split: coarse
236
+ refusals need no explanation, and the ones that do are the ones you can reach.
175
237
  - **Refusals are returned, never thrown.** A thrown backend error reaches the
176
238
  browser as "Unable to handle the request" with the reason discarded. Check
177
239
  `result.ok`.
@@ -179,7 +241,12 @@ Each is measured, and each will bite otherwise.
179
241
  the same code, so refusals cannot be used to enumerate ids.
180
242
  - **`_owner` is unusable.** Every elevated write stores `_owner: null`, and the
181
243
  app must write elevated. Declare `owner` on the collection and the gateway
182
- stamps it explicitly.
244
+ stamps it explicitly. Nor can an admin set `_owner` to another member by
245
+ passing it; create on someone's behalf with `onBehalfOf` instead.
246
+ - **Since 0.5.0 an owner value inside the record is ignored**, for visitors too.
247
+ 0.4.0 kept it when the caller had no member id, which let a visitor file a row
248
+ under any member. Code that relied on that passes `onBehalfOf` (with
249
+ `system: true` when the server chose the owner).
183
250
  - **`update` is checked against the stored row**, never the submitted one, so a
184
251
  caller cannot authorise themselves by sending an owner field they do not own.
185
252
  - **"Could not verify" is not "not allowed".** A failed roles read or enricher
package/backend.d.ts CHANGED
@@ -1,13 +1,35 @@
1
1
  export * from './types'
2
2
  import { Policy, Principal, Ability, SerialisedRule, Result, Clause, Scope } from './types'
3
3
 
4
- export interface AuditEvent {
5
- event: 'access.denied'
6
- action: string
7
- code: string
8
- caller: string | null
9
- detail?: unknown
10
- }
4
+ export type AuditEvent =
5
+ | {
6
+ event: 'access.denied'
7
+ action: string
8
+ code: string
9
+ caller: string | null
10
+ detail?: unknown
11
+ }
12
+ | {
13
+ /** A row was created in someone else's name. */
14
+ event: 'access.onBehalf'
15
+ action: string
16
+ caller: string | null
17
+ owner: string
18
+ system: boolean
19
+ collection: string
20
+ id: string
21
+ }
22
+ | {
23
+ /** A row moved from one owner to another. */
24
+ event: 'access.transfer'
25
+ action: 'assignOwner'
26
+ caller: string | null
27
+ from: string | null
28
+ owner: string | null
29
+ system: boolean
30
+ collection: string
31
+ id: string
32
+ }
11
33
 
12
34
  export interface CreateAccessOptions {
13
35
  /** Adds domain facts to the Principal — vendor membership, tenancy, staff rows. */
@@ -33,11 +55,37 @@ export interface DbOptions {
33
55
  limit?: number
34
56
  }
35
57
 
58
+ export interface InsertOptions extends DbOptions {
59
+ /**
60
+ * Create the row in this member's name instead of the caller's. Needs the `assignOwner`
61
+ * ability against the row, unless `system` is set. Any owner value inside the record
62
+ * itself is always ignored.
63
+ */
64
+ onBehalfOf?: string
65
+ /**
66
+ * The SERVER worked this owner out (e.g. a guest matched to an account by email), so the
67
+ * caller's `assignOwner` right is not checked. Still audited. Requires `onBehalfOf`.
68
+ */
69
+ system?: boolean
70
+ }
71
+
72
+ export interface TransferOptions {
73
+ principal: Principal
74
+ /** Skip the `assignOwner` check for a server-decided move. Still audited. */
75
+ system?: boolean
76
+ }
77
+
78
+ /** The action a caller needs to create or move a row in someone else's name. */
79
+ export declare const ASSIGN_OWNER: 'assignOwner'
80
+
36
81
  export interface Db {
37
82
  query(collection: string, opts: DbOptions): Promise<{ ok: true; data: unknown[]; scope: Scope }>
38
83
  get(collection: string, id: string, opts: DbOptions): Promise<Result<unknown>>
39
- insert(collection: string, record: Record<string, unknown>, opts: DbOptions): Promise<Result<unknown>>
84
+ insert(collection: string, record: Record<string, unknown>, opts: InsertOptions): Promise<Result<unknown>>
85
+ /** Never changes the owner or actor field; refuses `onBehalfOf` — use `transfer`. */
40
86
  update(collection: string, id: string, changes: Record<string, unknown>, opts: DbOptions): Promise<Result<unknown>>
87
+ /** Moves a row to another owner, or to none with `null`. */
88
+ transfer(collection: string, id: string, newOwner: string | null, opts: TransferOptions): Promise<Result<unknown>>
41
89
  remove(collection: string, id: string, opts: DbOptions): Promise<Result<unknown>>
42
90
  }
43
91
 
@@ -81,6 +129,13 @@ export declare function parseGates(source: string): Record<string, string>
81
129
  export declare function verifyGates(source: string, policy: Policy, options?: { complete?: boolean }): GateReport
82
130
  /** verifyGates, throwing with every problem in the message. For a test. */
83
131
  export declare function assertGates(source: string, policy: Policy, options?: { complete?: boolean }): true
132
+ /**
133
+ * Makes the policy the authority on the gate at runtime, by stamping each
134
+ * exported web method's `permission` property from `policy.api`. Call it once at
135
+ * the end of your `.web.js`, passing the exported bindings. Throws on any method
136
+ * missing from the policy.
137
+ */
138
+ export declare function applyGates(exported: Record<string, unknown>, policy: Policy): Record<string, string>
84
139
 
85
140
  export declare function backendPing(): { ok: boolean; side: string; version: string }
86
141
  export declare function backendMemberId(): Promise<string | null>
package/backend.js CHANGED
@@ -1,3 +1,3 @@
1
- var Yt=Object.create;var Y=Object.defineProperty;var Jt=Object.getOwnPropertyDescriptor;var Kt=Object.getOwnPropertyNames;var Zt=Object.getPrototypeOf,Ht=Object.prototype.hasOwnProperty;var Qt=(t,e)=>{for(var r in e)Y(t,r,{get:e[r],enumerable:!0})},st=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Kt(e))!Ht.call(t,s)&&s!==r&&Y(t,s,{get:()=>e[s],enumerable:!(n=Jt(e,s))||n.enumerable});return t};var Wt=(t,e,r)=>(r=t!=null?Yt(Zt(t)):{},st(e||!t||!t.__esModule?Y(r,"default",{value:t,enumerable:!0}):r,t)),Xt=t=>st(Y({},"__esModule",{value:!0}),t);var Qr={};Qt(Qr,{CASES:()=>rt,CODES:()=>O,KIND:()=>$,PACKAGE_VERSION:()=>tt,PolicyError:()=>M,SCOPE:()=>w,WHEN:()=>I,abilityFor:()=>ce,abilityFromRules:()=>Qe,anonymous:()=>at,applyClauses:()=>le,assertDeclared:()=>Tt,assertGates:()=>Rt,backendMemberId:()=>Hr,backendPing:()=>Zr,can:()=>v,caseTable:()=>kt,createAccess:()=>Kr,createPrincipal:()=>q,deny:()=>C,denyOpaque:()=>j,filterFor:()=>ue,hasRole:()=>J,isDenial:()=>it,normaliseRoles:()=>fe,ok:()=>ot,parseGates:()=>Xe,permissionFor:()=>ut,resolvePlaceholders:()=>St,resolveSubjects:()=>Z,resolveWhere:()=>ae,rulesFor:()=>k,validatePolicy:()=>K,verifyGates:()=>et});module.exports=Xt(Qr);var nt=require("wix-members-backend"),Bt=Wt(require("wix-users-backend"),1),zt=require("@wix/data"),Gt=require("@wix/essentials");var O={FORBIDDEN:"FORBIDDEN",UNAUTHENTICATED:"UNAUTHENTICATED",UNVERIFIED:"UNVERIFIED",NOT_FOUND:"NOT_FOUND",INVALID_POLICY:"INVALID_POLICY",INVALID_ARGUMENT:"INVALID_ARGUMENT"},M=class extends Error{constructor(e){super(e),this.name="PolicyError",this.code=O.INVALID_POLICY}};function ot(t){return{ok:!0,data:t===void 0?null:t}}function C(t,e,r){let n={ok:!1,code:t||O.FORBIDDEN};return e&&(n.action=e),r&&(n.detail=r),n}var it=t=>!!t&&t.ok===!1;function j(t){return C(O.NOT_FOUND,t)}var $={VISITOR:"visitor",MEMBER:"member",CAPABILITY:"capability",SERVICE:"service"};function fe(t){if(!Array.isArray(t))return[];let e=[];for(let r of t){if(typeof r=="string"){e.push(r);continue}if(!r||typeof r!="object")continue;let n=r.title||r.name||r.roleKey;n&&e.push(n)}return e}function q(t){let e=t||{},r=e.memberId||null,n=fe(e.roles);return{kind:e.kind||(r?$.MEMBER:$.VISITOR),memberId:r,roles:n,subjects:Array.isArray(e.subjects)?e.subjects.slice():[],domain:e.domain&&typeof e.domain=="object"?e.domain:{},unverified:!!e.unverified}}var at=()=>q({kind:$.VISITOR}),J=(t,e)=>t.roles.indexOf(e)!==-1;var I={ANYONE:"anyone",ANONYMOUS:"anonymous",MEMBER:"member"},E=t=>!!t&&typeof t=="object"&&!Array.isArray(t),er=t=>Array.isArray(t)?t:[t];function h(t,e){throw new M("policy"+t+": "+e)}function tr(t,e){let r=".subjects."+t;E(e)||h(r,"must be an object");let s=["when","role","domain"].filter(o=>e[o]!==void 0);if(s.length===0&&h(r,'needs exactly one of when/role/domain \u2014 "{}" is ambiguous between a visitor and a member'),s.length>1&&h(r,"has "+s.join(" and ")+"; use exactly one"),e.when!==void 0){let o=[I.ANYONE,I.ANONYMOUS,I.MEMBER];o.indexOf(e.when)===-1&&h(r+".when","must be one of "+o.join(", ")+" (got "+JSON.stringify(e.when)+")")}e.role!==void 0&&typeof e.role!="string"&&h(r+".role","must be a string"),e.domain!==void 0&&typeof e.domain!="string"&&h(r+".domain","must be a string")}function rr(t,e,r){let n=".rules["+e+"]";E(t)||h(n,"must be an object"),typeof t.subject!="string"&&h(n+".subject","must be a string"),r.indexOf(t.subject)===-1&&h(n+".subject",'"'+t.subject+'" is not declared in policy.subjects'),t.actions===void 0&&h(n+".actions","is required");for(let s of er(t.actions))typeof s!="string"&&h(n+".actions","must be a string or an array of strings");typeof t.resource!="string"&&h(n+".resource","must be a string"),t.where!==void 0&&!E(t.where)&&h(n+".where","must be an object")}var ct=["Anyone","SiteMember","Admin"];function nr(t,e,r){let n=".api."+t;E(e)||h(n,"must be an object"),ct.indexOf(e.permission)===-1&&h(n+".permission","must be one of "+ct.join(", ")+" (got "+JSON.stringify(e.permission)+")"),e.ability!==void 0&&((!Array.isArray(e.ability)||e.ability.length!==2)&&h(n+".ability","must be [action, resource]"),(typeof e.ability[0]!="string"||typeof e.ability[1]!="string")&&h(n+".ability","both entries must be strings")),e.subject!==void 0&&r.indexOf(e.subject)===-1&&h(n+".subject",'"'+e.subject+'" is not declared in policy.subjects')}function K(t){if(!E(t))throw new M("policy must be an object");E(t.subjects)||h(".subjects","is required and must be an object");let e=Object.keys(t.subjects);e.length===0&&h(".subjects","declares no subjects");for(let r of e)tr(r,t.subjects[r]);if(Array.isArray(t.rules)||h(".rules","is required and must be an array"),t.rules.forEach((r,n)=>rr(r,n,e)),t.api!==void 0){E(t.api)||h(".api","must be an object");for(let r of Object.keys(t.api))nr(r,t.api[r],e)}return t.collections!==void 0&&!E(t.collections)&&h(".collections","must be an object"),t}function Z(t,e){let r=new Set(t.subjects||[]);for(let n of Object.keys(e.subjects)){let s=e.subjects[n];(s.when===I.ANYONE||s.when===I.ANONYMOUS&&!t.memberId||s.when===I.MEMBER&&t.memberId||s.role!==void 0&&t.roles.indexOf(s.role)!==-1||s.domain!==void 0&&t.domain[s.domain])&&r.add(n)}return Array.from(r)}function ut(t,e){let r=t.api&&t.api[e];return r?r.permission:null}var H=class{constructor(e,r){this.operator=e,this.value=r,Object.defineProperty(this,"t",{writable:!0})}get notes(){return this.t}addNote(e){this.t=this.t||[],this.t.push(e)}},L=class extends H{},S=class extends L{constructor(e,r){if(!Array.isArray(r))throw new Error(`"${e}" operator expects to receive an array of conditions`);super(e,r)}},N="__itself__",_=class extends H{constructor(e,r,n){super(e,n),this.field=r}},me=new L("__null__",null),he=Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);function sr(t,e){return e instanceof S&&e.operator===t}function ye(t,e){return e.length===1?e[0]:new S(t,(function r(n,s,o){let i=o||[];for(let c=0,u=s.length;c<u;c++){let l=s[c];sr(n,l)?r(n,l.value,i):i.push(l)}return i})(t,e))}var or=t=>t,lt=()=>Object.create(null),ft=Object.defineProperty(lt(),"__@type@__",{value:"ignore value"});function ir(t,e,r=!1){if(!t||t&&t.constructor!==Object)return!1;for(let n in t)if(he(t,n)&&he(e,n)&&(!r||t[n]!==ft))return!0;return!1}function ar(t){let e=[];for(let r in t)he(t,r)&&t[r]!==ft&&e.push(r);return e}function de(t,e){e!==me&&t.push(e)}var be=t=>ye("and",t);var Q={compound(t,e,r){let n=(Array.isArray(e)?e:[e]).map(s=>r.parse(s));return new S(t.name,n)},field:(t,e,r)=>new _(t.name,r.field,e),document:(t,e)=>new L(t.name,e)},B=class{constructor(e,r=lt()){this.o=void 0,this.s=void 0,this.i=void 0,this.u=void 0,this.h=void 0,this.parse=this.parse.bind(this),this.u={operatorToConditionName:r.operatorToConditionName||or,defaultOperatorName:r.defaultOperatorName||"eq",mergeFinalConditions:r.mergeFinalConditions||be},this.o=Object.keys(e).reduce((n,s)=>(n[s]=Object.assign({name:this.u.operatorToConditionName(s)},e[s]),n),{}),this.s=Object.assign({},r.fieldContext,{field:"",query:{},parse:this.parse,hasOperators:n=>ir(n,this.o,r.useIgnoreValue)}),this.i=Object.assign({},r.documentContext,{parse:this.parse,query:{}}),this.h=r.useIgnoreValue?ar:Object.keys}setParse(e){this.parse=e,this.s.parse=e,this.i.parse=e}parseField(e,r,n,s){let o=this.o[r];if(!o)throw new Error(`Unsupported operator "${r}"`);if(o.type!=="field")throw new Error(`Unexpected ${o.type} operator "${r}" at field level`);return this.s.field=e,this.s.query=s,this.parseInstruction(o,n,this.s)}parseInstruction(e,r,n){return typeof e.validate=="function"&&e.validate(e,r),(e.parse||Q[e.type])(e,r,n)}parseFieldOperators(e,r){let n=[],s=this.h(r);for(let o=0,i=s.length;o<i;o++){let c=s[o];if(!this.o[c])throw new Error(`Field query for "${e}" may contain only operators or a plain object as a value`);de(n,this.parseField(e,c,r[c],r))}return n}parse(e){let r=[],n=this.h(e);this.i.query=e;for(let s=0,o=n.length;s<o;s++){let i=n[s],c=e[i],u=this.o[i];if(u){if(u.type!=="document"&&u.type!=="compound")throw new Error(`Cannot use parsing instruction for operator "${i}" in "document" context as it is supposed to be used in "${u.type}" context`);de(r,this.parseInstruction(u,c,this.i))}else this.s.hasOperators(c)?r.push(...this.parseFieldOperators(i,c)):de(r,this.parseField(i,this.u.defaultOperatorName,c,e))}return this.u.mergeFinalConditions(r)}};function pe(t,e){let r=t[e];if(typeof r!="function")throw new Error(`Unable to interpret "${e}" condition. Did you forget to register interpreter for it?`);return r}function cr(t){return t.operator}function dt(t,e){let r=e,n=r&&r.getInterpreterName||cr,s;switch(r?r.numberOfArguments:0){case 1:s=i=>{let c=n(i,r);return pe(t,c)(i,o)};break;case 3:s=(i,c,u)=>{let l=n(i,r);return pe(t,l)(i,c,u,o)};break;default:s=(i,c)=>{let u=n(i,r);return pe(t,u)(i,c,o)}}let o=Object.assign({},r,{interpret:s});return o.interpret}function pt(t,e){return(r,...n)=>{let s=t(r,...n),o=e.bind(null,s);return o.ast=s,o}}var on=B.prototype.parseInstruction;function ht(t,e){if(!Array.isArray(e))throw new Error(`"${t.name}" expects value to be an array`)}function mt(t,e){if(ht(t,e),!e.length)throw new Error(`"${t.name}" expects to have at least one element in array`)}var ge=t=>(e,r)=>{if(typeof r!==t)throw new Error(`"${e.name}" expects value to be a "${t}"`)},yt={type:"compound",validate:mt,parse(t,e,{parse:r}){let n=e.map(s=>r(s));return ye(t.name,n)}},ur=yt,lr={type:"compound",validate:mt},fr={type:"field",validate(t,e){if(!(e&&(e instanceof RegExp||e.constructor===Object)))throw new Error(`"${t.name}" expects to receive either regular expression or object of field operators`)},parse(t,e,r){let n=e instanceof RegExp?new _("regex",r.field,e):r.parse(e,r);return new S(t.name,[n])}},xe={type:"field",validate(t,e){if(!e||e.constructor!==Object)throw new Error(`"${t.name}" expects to receive an object with nested query or field level operators`)},parse(t,e,{parse:r,field:n,hasOperators:s}){let o=s(e)?r(e,{field:N}):r(e);return new _(t.name,n,o)}},Oe={type:"field",validate:ge("number")},z={type:"field",validate:ht},ve=z,we=z,dr={type:"field",validate(t,e){if(!Array.isArray(e)||e.length!==2)throw new Error(`"${t.name}" expects an array with 2 numeric elements`)}},je={type:"field",validate:ge("boolean")},X={type:"field",validate:function(t,e){if(!(typeof e=="string"||typeof e=="number"||e instanceof Date))throw new Error(`"${t.name}" expects value to be comparable (i.e., string, number or date)`)}},G=X,Ae=G,$e=G,ee={type:"field"},Ee=ee,Ie={type:"field",validate(t,e){if(!(e instanceof RegExp)&&typeof e!="string")throw new Error(`"${t.name}" expects value to be a regular expression or a string that represents regular expression`)},parse(t,e,r){let n=typeof e=="string"?new RegExp(e,r.query.$options||""):e;return new _(t.name,r.field,n)}},Ne={type:"field",parse:()=>me},pr={type:"document",validate:ge("function")},hr=Object.freeze({__proto__:null,$and:yt,$or:ur,$nor:lr,$not:fr,$elemMatch:xe,$size:Oe,$in:z,$nin:ve,$all:we,$mod:dr,$exists:je,$gte:X,$gt:G,$lt:Ae,$lte:$e,$eq:ee,$ne:Ee,$regex:Ie,$options:Ne,$where:pr}),W=class extends B{constructor(e){super(e,{defaultOperatorName:"$eq",operatorToConditionName:r=>r.slice(1)})}parse(e,r){return r&&r.field?be(this.parseFieldOperators(r.field,e)):super.parse(e)}},te=hr;function Fe(t,e,r){for(let n=0,s=t.length;n<s;n++)if(r(t[n],e)===0)return!0;return!1}function Me(t,e){return Array.isArray(t)&&Number.isNaN(Number(e))}function bt(t,e,r){if(!Me(t,e))return r(t,e);let n=[];for(let s=0;s<t.length;s++){let o=r(t[s],e);o!==void 0&&(n=n.concat(o))}return n}function R(t){return(e,r,n)=>{let s=n.get(r,e.field);return Array.isArray(s)?s.some(o=>t(e,o,n)):t(e,s,n)}}var mr=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty),yr=(t,e)=>t[e];function gt(t,e,r){let n=e.lastIndexOf(".");return n===-1?[t,e]:[r(t,e.slice(0,n)),e.slice(n+1)]}function br(t,e,r=yr){if(e===N)return t;if(!t)throw new Error(`Unable to get field "${e}" out of ${String(t)}.`);return(function(n,s,o){if(s.indexOf(".")===-1)return bt(n,s,o);let i=s.split("."),c=n;for(let u=0,l=i.length;u<l;u++)if(c=bt(c,i[u],o),!c||typeof c!="object")return u<l-1?void 0:c;return c})(t,e,r)}function Ce(t,e){return t===e?0:t>e?1:-1}function Se(t,e={}){return dt(t,Object.assign({get:br,compare:Ce},e))}var xt=(t,e,{interpret:r})=>t.value.some(n=>r(n,e)),gr=(t,e,r)=>!xt(t,e,r),_e=(t,e,{interpret:r})=>t.value.every(n=>r(n,e)),xr=(t,e,{interpret:r})=>!r(t.value[0],e),re=(t,e,{compare:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&!Array.isArray(t.value)?Fe(s,t.value,r):r(s,t.value)===0},Re=(t,e,r)=>!re(t,e,r),ke=R((t,e,r)=>{let n=r.compare(e,t.value);return n===0||n===-1}),De=R((t,e,r)=>r.compare(e,t.value)===-1),Pe=R((t,e,r)=>r.compare(e,t.value)===1),Te=R((t,e,r)=>{let n=r.compare(e,t.value);return n===0||n===1}),Ue=(t,e,{get:r})=>{if(t.field===N)return e!==void 0;let[n,s]=gt(e,t.field,r),o=i=>i==null?!!i===t.value:mr(i,s)===t.value;return Me(n,s)?n.some(o):o(n)},Or=R((t,e)=>typeof e=="number"&&e%t.value[0]===t.value[1]),qe=(t,e,{get:r})=>{let[n,s]=gt(e,t.field,r),o=i=>{let c=r(i,s);return Array.isArray(c)&&c.length===t.value};return t.field!==N&&Me(n,s)?n.some(o):o(n)},Le=R((t,e)=>typeof e=="string"&&t.value.test(e)),V=R((t,e,{compare:r})=>Fe(t.value,e,r)),Be=(t,e,r)=>!V(t,e,r),ze=(t,e,{compare:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&t.value.every(o=>Fe(s,o,r))},Ge=(t,e,{interpret:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&s.some(o=>r(t.value,o))},vr=(t,e)=>t.value.call(e),wr=Object.freeze({__proto__:null,or:xt,nor:gr,and:_e,not:xr,eq:re,ne:Re,lte:ke,lt:De,gt:Pe,gte:Te,exists:Ue,mod:Or,size:qe,regex:Le,within:V,nin:Be,all:ze,elemMatch:Ge,where:vr}),ne=Object.assign({},wr,{in:V}),dn=Se(ne);function Ot(t){return t===null||typeof t!="object"?t:t instanceof Date?t.getTime():t&&typeof t.toJSON=="function"?t.toJSON():t}var jr=(t,e)=>Ce(Ot(t),Ot(e));function se(t,e,r){let n=new W(t),s=Se(e,Object.assign({compare:jr},r));if(r&&r.forPrimitives){let o={field:N},i=n.parse;n.setParse(c=>i(c,o))}return pt(n.parse,s)}var bn=se(te,ne),gn=se(["$and","$or"].reduce((t,e)=>(t[e]=Object.assign({},t[e],{type:"field"}),t),Object.assign({},te,{$nor:Object.assign({},te.$nor,{type:"field",parse:Q.compound})})),ne,{forPrimitives:!0});var Et=Object.hasOwn||((t,e)=>Object.prototype.hasOwnProperty.call(t,e));function Ve(t){return Array.isArray(t)?t:[t]}var P="__caslSubjectType__";function It(t,e){if(e){if(!Et(e,P))Object.defineProperty(e,P,{value:t});else if(t!==e[P])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[P]}`)}return e}var ie=t=>{let e=typeof t;return e==="string"||e==="function"},Nt=t=>t.modelName||t.name;function Ar(t){return typeof t=="string"?t:Nt(t)}function Ft(t){return Et(t,P)?t[P]:Nt(t.constructor)}var vt={function:t=>t.constructor,string:Ft};function wt(t,e,r){for(let n=r;n<e.length;n++)t.push(e[n])}function jt(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let r=0,n=0,s=[];for(;r<t.length&&n<e.length;)t[r].priority<e[n].priority?(s.push(t[r]),r++):t[r].priority>e[n].priority?(s.push(e[n]),n++):(s.push(t[r]),r++,n++);return wt(s,t,r),wt(s,e,n),s}function oe(t,e,r){let n=t.get(e);return n||(n=r(),t.set(e,n)),n}var $r=t=>t;function Er(t,e){let r;for(let n=0;n<t.length;n++){let s=e(t[n]);r&&s&&r.push(t[n]),s||(r??=t.slice(0,n))}return r||t}function Ir(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')}var Ye=class{constructor(e,r,n=0){Ir(e,r),this.action=r.resolveAction(e.action),this.subject=e.subject,this.inverted=!!e.inverted,this.conditions=e.conditions,this.reason=e.reason,this.origin=e,this.fields=e.fields?Ve(e.fields):void 0,this.priority=n,this.t=r}i(){return this.conditions&&!this.o&&(this.o=this.t.conditionsMatcher(this.conditions)),this.o}get ast(){let e=this.i();return e?e.ast:void 0}matchesConditions(e){return this.conditions?!e||ie(e)?!this.inverted:this.i()(e):!0}matchesField(e){return this.fields?e?(this.u||(this.u=this.t.fieldMatcher(this.fields)),this.u(e)):!this.inverted:!0}};function Nr(t,e){let r={value:t,prev:e,next:null};return e&&(e.next=r),r}function Fr(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t.next=t.prev=null}var At=()=>({rules:[],merged:!1}),$t=()=>new Map,Je=class{constructor(e=[],r={}){this.h=!1,this.l=new Map,this.p={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||$r},this.$=r.anyAction||"manage",this.A=r.anySubjectType||"all",this.m=e,this.M=!!r.detectSubjectType,this.j=r.detectSubjectType||Ft,this.v(e)}get rules(){return this.m}detectSubjectType(e){return ie(e)?e:e?this.j(e):this.A}update(e){let r={rules:e,ability:this,target:this};return this._("update",r),this.m=e,this.v(e),this._("updated",r),this}v(e){let r=new Map,n;for(let s=e.length-1;s>=0;s--){let o=e.length-s-1,i=new Ye(e[s],this.p,o),c=Ve(i.action),u=Ve(i.subject||this.A);!this.h&&i.fields&&(this.h=!0);for(let l=0;l<u.length;l++){let a=oe(r,u[l],$t);n===void 0&&(n=typeof u[l]),typeof u[l]!==n&&n!=="mixed"&&(n="mixed");for(let d=0;d<c.length;d++)oe(a,c[d],At).rules.push(i)}}if(this.l=r,n!=="mixed"&&!this.M){let s=vt[n]||vt.string;this.j=s}}possibleRulesFor(e,r=this.A){if(!ie(r))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');let n=oe(this.l,r,$t),s=oe(n,e,At);if(s.merged)return s.rules;let o=e!==this.$&&n.has(this.$)?n.get(this.$).rules:void 0,i=jt(s.rules,o);return r!==this.A&&(i=jt(i,this.possibleRulesFor(e,this.A))),s.rules=i,s.merged=!0,i}rulesFor(e,r,n){let s=this.possibleRulesFor(e,r);if(n&&typeof n!="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");return this.h?Er(s,o=>o.matchesField(n)):s}actionsFor(e){if(!ie(e))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');let r=new Set,n=this.l.get(e);n&&Array.from(n.keys()).forEach(o=>r.add(o));let s=e!==this.A?this.l.get(this.A):void 0;return s&&Array.from(s.keys()).forEach(o=>r.add(o)),Array.from(r)}on(e,r){this.F=this.F||new Map;let n=this.F,s=n.get(e)||null,o=Nr(r,s);return n.set(e,o),()=>{let i=n.get(e);!o.next&&!o.prev&&i===o?n.delete(e):o===i&&n.set(e,o.prev),Fr(o)}}_(e,r){if(!this.F)return;let n=this.F.get(e)||null,s=[];for(;n!==null;)s.push(n.value),n=n.prev;for(let o=0;o<s.length;o++)s[o](r)}},Ke=class extends Je{can(e,r,n){let s=this.relevantRuleFor(e,r,n);return!!s&&!s.inverted}relevantRuleFor(e,r,n){let s=this.detectSubjectType(r),o=this.rulesFor(e,s,n);for(let i=0,c=o.length;i<c;i++)if(o[i].matchesConditions(r))return o[i];return null}cannot(e,r,n){return!this.can(e,r,n)}},Mr={$eq:ee,$ne:Ee,$lt:Ae,$lte:$e,$gt:G,$gte:X,$in:z,$nin:ve,$all:we,$size:Oe,$regex:Ie,$options:Ne,$elemMatch:xe,$exists:je},Cr={eq:re,ne:Re,lt:De,lte:ke,gt:Pe,gte:Te,in:V,nin:Be,all:ze,size:qe,regex:Le,elemMatch:Ge,exists:Ue,and:_e};var Sr=se(Mr,Cr),_r=/[-/\\^$+?.()|[\]{}]/g,Rr=/\.?\*+\.?/g,kr=/\*+/,Dr=/\./g;function Pr(t,e,r){let n=r[0]==="*"||t[0]==="."&&t[t.length-1]==="."?"+":"*",s=t.indexOf("**")===-1?"[^.]":".",o=t.replace(Dr,"\\$&").replace(kr,s+n);return e+t.length===r.length?`(?:${o})?`:o}function Tr(t,e,r){return t==="."&&(r[e-1]==="*"||r[e+1]==="*")?t:`\\${t}`}function Ur(t){let e=t.map(n=>n.replace(_r,Tr).replace(Rr,Pr)),r=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${r}$`)}var qr=t=>{let e;return r=>(typeof e>"u"&&(e=t.every(n=>n.indexOf("*")===-1)?null:Ur(t)),e===null?t.indexOf(r)!==-1:e.test(r))};function Mt(t=[],e={}){return new Ke(t,Object.assign({conditionsMatcher:Sr,fieldMatcher:qr},e))}var Lr=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`,Ct=function(e){this.message=e};Ct.prototype=Object.create(Error.prototype);var Ze=class extends Ct{static setDefaultMessage(e){this.P=typeof e=="string"?()=>e:e}static from(e){return new this(e)}constructor(e){super(""),this.ability=e,typeof Error.captureStackTrace=="function"&&(this.name="ForbiddenError",Error.captureStackTrace(this,this.constructor))}setMessage(e){return this.message=e,this}throwUnlessCan(e,r,n){let s=this.unlessCan(e,r,n);if(s)throw s}unlessCan(e,r,n){let s=this.ability.relevantRuleFor(e,r,n);if(s&&!s.inverted)return;this.action=e,this.subject=r,this.subjectType=Ar(this.ability.detectSubjectType(r)),this.field=n;let o=s?s.reason:"";return this.message=this.message||o||this.constructor.P(this),this}};Ze.P=Lr;var An=Object.freeze({__proto__:null});function He(t,e,r){if(t==null)return t;if(typeof t=="string"){if(t.indexOf("$principal.")!==0)return t;let s=t.slice(11).split(".").reduce((o,i)=>o==null?o:o[i],e);return s==null&&(r.unresolved=!0),s}if(Array.isArray(t))return t.map(n=>He(n,e,r));if(typeof t=="object"){let n={};for(let s of Object.keys(t))n[s]=He(t[s],e,r);return n}return t}function ae(t,e){let r={unresolved:!1};return{conditions:He(t,e,r),unresolved:r.unresolved}}function St(t,e){return ae(t,e).conditions}function k(t,e){let r=Z(t,e),n=[];for(let s of e.rules){if(r.indexOf(s.subject)===-1)continue;let o={action:s.actions,subject:s.resource};if(s.where){let{conditions:i,unresolved:c}=ae(s.where,t);if(c)continue;o.conditions=i}n.push(o)}return n}function Qe(t){return Mt(Array.isArray(t)?t:[])}function ce(t,e){return Qe(k(t,e))}function v(t,e,r,n){return n==null?t.can(e,r):t.can(e,It(r,Object.assign({},n)))}var w={ALL:"all",NONE:"none",FIELDS:"fields",AMBIGUOUS:"ambiguous"},_t={$in:"in",$nin:"nin",$ne:"ne",$gt:"gt",$gte:"gte",$lt:"lt",$lte:"lte"};function Br(t){let e=[];for(let r of Object.keys(t)){let n=t[r];if(n===null||typeof n!="object"||Array.isArray(n)){e.push({field:r,op:"eq",value:n});continue}let s=Object.keys(n);if(s.length!==1||!_t[s[0]])return null;e.push({field:r,op:_t[s[0]],value:n[s[0]]})}return e}var zr=(t,e)=>t==="manage"||t===e||Array.isArray(t)&&(t.indexOf(e)!==-1||t.indexOf("manage")!==-1),Gr=(t,e)=>t==="all"||t===e;function ue(t,e,r,n){let s=k(t,e).filter(i=>zr(i.action,r)&&Gr(i.subject,n));if(s.length===0)return{scope:w.NONE,clauses:[]};if(s.some(i=>!i.conditions))return{scope:w.ALL,clauses:[]};if(s.length>1)return{scope:w.AMBIGUOUS,clauses:[]};let o=Br(s[0].conditions);return o?{scope:w.FIELDS,clauses:o}:{scope:w.AMBIGUOUS,clauses:[]}}function le(t,e){let r=t;for(let n of e)n.op==="in"?r=r.hasSome(n.field,n.value):n.op==="nin"?r=r.not(r.hasSome(n.field,n.value)):r=r[n.op](n.field,n.value);return r}var We=/export\s+const\s+([A-Za-z0-9_$]+)\s*=\s*webMethod\s*\(\s*Permissions\s*\.\s*([A-Za-z0-9_$]+)/g,Vr=[[/export\s*{\s*[A-Za-z0-9_$,\s]+}/,"export { x } \u2014 the call and the export must be one statement"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*Permissions\s*\[/,"Permissions['X'] \u2014 the property must be dotted and literal"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*[A-Za-z0-9_$]+\s*\(/,"a computed permission \u2014 it must be written out as Permissions.LEVEL"]];function Xe(t){let e={},r=String(t||"");We.lastIndex=0;let n=We.exec(r);for(;n;)e[n[1]]=n[2],n=We.exec(r);return e}function et(t,e,r){let n=r||{},s=e&&e.api||{},o=Xe(t),i=String(t||""),c=[],u=[];for(let f of Object.keys(o)){let p=s[f];p?p.permission!==o[f]&&c.push({name:f,declared:p.permission,written:o[f]}):u.push({name:f,gate:o[f]})}let l=n.complete?Object.keys(s).filter(f=>!(f in o)):[],a=[];for(let[f,p]of Vr)f.test(i)&&a.push(p);return{ok:c.length+u.length+l.length+a.length===0,found:o,mismatched:c,undeclared:u,missing:l,suspect:a}}function Rt(t,e,r){let n=et(t,e,r);if(n.ok)return!0;let s=[];for(let o of n.mismatched)s.push(o.name+": policy says "+o.declared+", the export says "+o.written);for(let o of n.undeclared)s.push(o.name+": gated "+o.gate+" but missing from policy.api");for(let o of n.missing)s.push(o+": declared in policy.api but not exported here");for(let o of n.suspect)s.push("unreachable export shape \u2014 "+o);throw new Error(`wix-access: web-method gates do not match the policy:
1
+ var Xt=Object.create;var Q=Object.defineProperty;var er=Object.getOwnPropertyDescriptor;var tr=Object.getOwnPropertyNames;var rr=Object.getPrototypeOf,nr=Object.prototype.hasOwnProperty;var sr=(t,e)=>{for(var r in e)Q(t,r,{get:e[r],enumerable:!0})},ft=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of tr(e))!nr.call(t,s)&&s!==r&&Q(t,s,{get:()=>e[s],enumerable:!(n=er(e,s))||n.enumerable});return t};var or=(t,e,r)=>(r=t!=null?Xt(rr(t)):{},ft(e||!t||!t.__esModule?Q(r,"default",{value:t,enumerable:!0}):r,t)),ir=t=>ft(Q({},"__esModule",{value:!0}),t);var an={};sr(an,{ASSIGN_OWNER:()=>F,CASES:()=>ct,CODES:()=>x,KIND:()=>R,PACKAGE_VERSION:()=>at,PolicyError:()=>T,SCOPE:()=>M,WHEN:()=>D,abilityFor:()=>pe,abilityFromRules:()=>nt,anonymous:()=>ht,applyClauses:()=>me,applyGates:()=>qt,assertDeclared:()=>Yt,assertGates:()=>Bt,backendMemberId:()=>on,backendPing:()=>sn,can:()=>$,caseTable:()=>Gt,createAccess:()=>nn,createPrincipal:()=>Y,deny:()=>I,denyOpaque:()=>N,filterFor:()=>he,hasRole:()=>X,isDenial:()=>pt,normaliseRoles:()=>be,ok:()=>dt,parseGates:()=>ot,permissionFor:()=>yt,resolvePlaceholders:()=>Ut,resolveSubjects:()=>G,resolveWhere:()=>de,rulesFor:()=>B,validatePolicy:()=>ee,verifyGates:()=>it});module.exports=ir(an);var ut=require("wix-members-backend"),Zt=or(require("wix-users-backend"),1),Ht=require("@wix/data"),Qt=require("@wix/essentials");var x={FORBIDDEN:"FORBIDDEN",UNAUTHENTICATED:"UNAUTHENTICATED",UNVERIFIED:"UNVERIFIED",NOT_FOUND:"NOT_FOUND",INVALID_POLICY:"INVALID_POLICY",INVALID_ARGUMENT:"INVALID_ARGUMENT"},T=class extends Error{constructor(e){super(e),this.name="PolicyError",this.code=x.INVALID_POLICY}};function dt(t){return{ok:!0,data:t===void 0?null:t}}function I(t,e,r){let n={ok:!1,code:t||x.FORBIDDEN};return e&&(n.action=e),r&&(n.detail=r),n}var pt=t=>!!t&&t.ok===!1;function N(t){return I(x.NOT_FOUND,t)}var R={VISITOR:"visitor",MEMBER:"member",CAPABILITY:"capability",SERVICE:"service"};function be(t){if(!Array.isArray(t))return[];let e=[];for(let r of t){if(typeof r=="string"){e.push(r);continue}if(!r||typeof r!="object")continue;let n=r.title||r.name||r.roleKey;n&&e.push(n)}return e}function Y(t){let e=t||{},r=e.memberId||null,n=be(e.roles);return{kind:e.kind||(r?R.MEMBER:R.VISITOR),memberId:r,roles:n,subjects:Array.isArray(e.subjects)?e.subjects.slice():[],domain:e.domain&&typeof e.domain=="object"?e.domain:{},unverified:!!e.unverified}}var ht=()=>Y({kind:R.VISITOR}),X=(t,e)=>t.roles.indexOf(e)!==-1;var D={ANYONE:"anyone",ANONYMOUS:"anonymous",MEMBER:"member"},_=t=>!!t&&typeof t=="object"&&!Array.isArray(t),ar=t=>Array.isArray(t)?t:[t];function m(t,e){throw new T("policy"+t+": "+e)}function cr(t,e){let r=".subjects."+t;_(e)||m(r,"must be an object");let s=["when","role","domain"].filter(o=>e[o]!==void 0);if(s.length===0&&m(r,'needs exactly one of when/role/domain \u2014 "{}" is ambiguous between a visitor and a member'),s.length>1&&m(r,"has "+s.join(" and ")+"; use exactly one"),e.when!==void 0){let o=[D.ANYONE,D.ANONYMOUS,D.MEMBER];o.indexOf(e.when)===-1&&m(r+".when","must be one of "+o.join(", ")+" (got "+JSON.stringify(e.when)+")")}e.role!==void 0&&typeof e.role!="string"&&m(r+".role","must be a string"),e.domain!==void 0&&typeof e.domain!="string"&&m(r+".domain","must be a string")}function ur(t,e,r){let n=".rules["+e+"]";_(t)||m(n,"must be an object"),typeof t.subject!="string"&&m(n+".subject","must be a string"),r.indexOf(t.subject)===-1&&m(n+".subject",'"'+t.subject+'" is not declared in policy.subjects'),t.actions===void 0&&m(n+".actions","is required");for(let s of ar(t.actions))typeof s!="string"&&m(n+".actions","must be a string or an array of strings");typeof t.resource!="string"&&m(n+".resource","must be a string"),t.where!==void 0&&!_(t.where)&&m(n+".where","must be an object")}var mt=["Anyone","SiteMember","Admin"];function lr(t,e,r){let n=".api."+t;_(e)||m(n,"must be an object"),mt.indexOf(e.permission)===-1&&m(n+".permission","must be one of "+mt.join(", ")+" (got "+JSON.stringify(e.permission)+")"),e.ability!==void 0&&((!Array.isArray(e.ability)||e.ability.length!==2)&&m(n+".ability","must be [action, resource]"),(typeof e.ability[0]!="string"||typeof e.ability[1]!="string")&&m(n+".ability","both entries must be strings")),e.subject!==void 0&&r.indexOf(e.subject)===-1&&m(n+".subject",'"'+e.subject+'" is not declared in policy.subjects')}var fr=["resource","owner","actor","tenant","profile"];function dr(t,e){let r=".collections."+t;_(e)||m(r,"must be an object");for(let n of fr)e[n]!==void 0&&(typeof e[n]!="string"||!e[n])&&m(r+"."+n,"must be a non-empty string");e.owner!==void 0&&e.owner===e.actor&&m(r,'owner and actor must be different fields (both are "'+e.owner+'")')}function ee(t){if(!_(t))throw new T("policy must be an object");_(t.subjects)||m(".subjects","is required and must be an object");let e=Object.keys(t.subjects);e.length===0&&m(".subjects","declares no subjects");for(let r of e)cr(r,t.subjects[r]);if(Array.isArray(t.rules)||m(".rules","is required and must be an array"),t.rules.forEach((r,n)=>ur(r,n,e)),t.api!==void 0){_(t.api)||m(".api","must be an object");for(let r of Object.keys(t.api))lr(r,t.api[r],e)}if(t.collections!==void 0){_(t.collections)||m(".collections","must be an object");for(let r of Object.keys(t.collections))dr(r,t.collections[r])}return t}function G(t,e){let r=new Set(t.subjects||[]);for(let n of Object.keys(e.subjects)){let s=e.subjects[n];(s.when===D.ANYONE||s.when===D.ANONYMOUS&&!t.memberId||s.when===D.MEMBER&&t.memberId||s.role!==void 0&&t.roles.indexOf(s.role)!==-1||s.domain!==void 0&&t.domain[s.domain])&&r.add(n)}return Array.from(r)}function yt(t,e){let r=t.api&&t.api[e];return r?r.permission:null}var te=class{constructor(e,r){this.operator=e,this.value=r,Object.defineProperty(this,"t",{writable:!0})}get notes(){return this.t}addNote(e){this.t=this.t||[],this.t.push(e)}},W=class extends te{},P=class extends W{constructor(e,r){if(!Array.isArray(r))throw new Error(`"${e}" operator expects to receive an array of conditions`);super(e,r)}},k="__itself__",U=class extends te{constructor(e,r,n){super(e,n),this.field=r}},ve=new W("__null__",null),xe=Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);function pr(t,e){return e instanceof P&&e.operator===t}function we(t,e){return e.length===1?e[0]:new P(t,(function r(n,s,o){let i=o||[];for(let a=0,l=s.length;a<l;a++){let c=s[a];pr(n,c)?r(n,c.value,i):i.push(c)}return i})(t,e))}var hr=t=>t,bt=()=>Object.create(null),gt=Object.defineProperty(bt(),"__@type@__",{value:"ignore value"});function mr(t,e,r=!1){if(!t||t&&t.constructor!==Object)return!1;for(let n in t)if(xe(t,n)&&xe(e,n)&&(!r||t[n]!==gt))return!0;return!1}function yr(t){let e=[];for(let r in t)xe(t,r)&&t[r]!==gt&&e.push(r);return e}function ge(t,e){e!==ve&&t.push(e)}var je=t=>we("and",t);var re={compound(t,e,r){let n=(Array.isArray(e)?e:[e]).map(s=>r.parse(s));return new P(t.name,n)},field:(t,e,r)=>new U(t.name,r.field,e),document:(t,e)=>new W(t.name,e)},J=class{constructor(e,r=bt()){this.o=void 0,this.s=void 0,this.i=void 0,this.u=void 0,this.h=void 0,this.parse=this.parse.bind(this),this.u={operatorToConditionName:r.operatorToConditionName||hr,defaultOperatorName:r.defaultOperatorName||"eq",mergeFinalConditions:r.mergeFinalConditions||je},this.o=Object.keys(e).reduce((n,s)=>(n[s]=Object.assign({name:this.u.operatorToConditionName(s)},e[s]),n),{}),this.s=Object.assign({},r.fieldContext,{field:"",query:{},parse:this.parse,hasOperators:n=>mr(n,this.o,r.useIgnoreValue)}),this.i=Object.assign({},r.documentContext,{parse:this.parse,query:{}}),this.h=r.useIgnoreValue?yr:Object.keys}setParse(e){this.parse=e,this.s.parse=e,this.i.parse=e}parseField(e,r,n,s){let o=this.o[r];if(!o)throw new Error(`Unsupported operator "${r}"`);if(o.type!=="field")throw new Error(`Unexpected ${o.type} operator "${r}" at field level`);return this.s.field=e,this.s.query=s,this.parseInstruction(o,n,this.s)}parseInstruction(e,r,n){return typeof e.validate=="function"&&e.validate(e,r),(e.parse||re[e.type])(e,r,n)}parseFieldOperators(e,r){let n=[],s=this.h(r);for(let o=0,i=s.length;o<i;o++){let a=s[o];if(!this.o[a])throw new Error(`Field query for "${e}" may contain only operators or a plain object as a value`);ge(n,this.parseField(e,a,r[a],r))}return n}parse(e){let r=[],n=this.h(e);this.i.query=e;for(let s=0,o=n.length;s<o;s++){let i=n[s],a=e[i],l=this.o[i];if(l){if(l.type!=="document"&&l.type!=="compound")throw new Error(`Cannot use parsing instruction for operator "${i}" in "document" context as it is supposed to be used in "${l.type}" context`);ge(r,this.parseInstruction(l,a,this.i))}else this.s.hasOperators(a)?r.push(...this.parseFieldOperators(i,a)):ge(r,this.parseField(i,this.u.defaultOperatorName,a,e))}return this.u.mergeFinalConditions(r)}};function Oe(t,e){let r=t[e];if(typeof r!="function")throw new Error(`Unable to interpret "${e}" condition. Did you forget to register interpreter for it?`);return r}function br(t){return t.operator}function Ot(t,e){let r=e,n=r&&r.getInterpreterName||br,s;switch(r?r.numberOfArguments:0){case 1:s=i=>{let a=n(i,r);return Oe(t,a)(i,o)};break;case 3:s=(i,a,l)=>{let c=n(i,r);return Oe(t,c)(i,a,l,o)};break;default:s=(i,a)=>{let l=n(i,r);return Oe(t,l)(i,a,o)}}let o=Object.assign({},r,{interpret:s});return o.interpret}function xt(t,e){return(r,...n)=>{let s=t(r,...n),o=e.bind(null,s);return o.ast=s,o}}var mn=J.prototype.parseInstruction;function vt(t,e){if(!Array.isArray(e))throw new Error(`"${t.name}" expects value to be an array`)}function wt(t,e){if(vt(t,e),!e.length)throw new Error(`"${t.name}" expects to have at least one element in array`)}var Ae=t=>(e,r)=>{if(typeof r!==t)throw new Error(`"${e.name}" expects value to be a "${t}"`)},jt={type:"compound",validate:wt,parse(t,e,{parse:r}){let n=e.map(s=>r(s));return we(t.name,n)}},gr=jt,Or={type:"compound",validate:wt},xr={type:"field",validate(t,e){if(!(e&&(e instanceof RegExp||e.constructor===Object)))throw new Error(`"${t.name}" expects to receive either regular expression or object of field operators`)},parse(t,e,r){let n=e instanceof RegExp?new U("regex",r.field,e):r.parse(e,r);return new P(t.name,[n])}},Ee={type:"field",validate(t,e){if(!e||e.constructor!==Object)throw new Error(`"${t.name}" expects to receive an object with nested query or field level operators`)},parse(t,e,{parse:r,field:n,hasOperators:s}){let o=s(e)?r(e,{field:k}):r(e);return new U(t.name,n,o)}},$e={type:"field",validate:Ae("number")},K={type:"field",validate:vt},Ie=K,Ne=K,vr={type:"field",validate(t,e){if(!Array.isArray(e)||e.length!==2)throw new Error(`"${t.name}" expects an array with 2 numeric elements`)}},Fe={type:"field",validate:Ae("boolean")},se={type:"field",validate:function(t,e){if(!(typeof e=="string"||typeof e=="number"||e instanceof Date))throw new Error(`"${t.name}" expects value to be comparable (i.e., string, number or date)`)}},Z=se,Me=Z,Ce=Z,oe={type:"field"},Se=oe,_e={type:"field",validate(t,e){if(!(e instanceof RegExp)&&typeof e!="string")throw new Error(`"${t.name}" expects value to be a regular expression or a string that represents regular expression`)},parse(t,e,r){let n=typeof e=="string"?new RegExp(e,r.query.$options||""):e;return new U(t.name,r.field,n)}},Re={type:"field",parse:()=>ve},wr={type:"document",validate:Ae("function")},jr=Object.freeze({__proto__:null,$and:jt,$or:gr,$nor:Or,$not:xr,$elemMatch:Ee,$size:$e,$in:K,$nin:Ie,$all:Ne,$mod:vr,$exists:Fe,$gte:se,$gt:Z,$lt:Me,$lte:Ce,$eq:oe,$ne:Se,$regex:_e,$options:Re,$where:wr}),ne=class extends J{constructor(e){super(e,{defaultOperatorName:"$eq",operatorToConditionName:r=>r.slice(1)})}parse(e,r){return r&&r.field?je(this.parseFieldOperators(r.field,e)):super.parse(e)}},ie=jr;function De(t,e,r){for(let n=0,s=t.length;n<s;n++)if(r(t[n],e)===0)return!0;return!1}function ke(t,e){return Array.isArray(t)&&Number.isNaN(Number(e))}function At(t,e,r){if(!ke(t,e))return r(t,e);let n=[];for(let s=0;s<t.length;s++){let o=r(t[s],e);o!==void 0&&(n=n.concat(o))}return n}function L(t){return(e,r,n)=>{let s=n.get(r,e.field);return Array.isArray(s)?s.some(o=>t(e,o,n)):t(e,s,n)}}var Ar=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty),Er=(t,e)=>t[e];function Et(t,e,r){let n=e.lastIndexOf(".");return n===-1?[t,e]:[r(t,e.slice(0,n)),e.slice(n+1)]}function $r(t,e,r=Er){if(e===k)return t;if(!t)throw new Error(`Unable to get field "${e}" out of ${String(t)}.`);return(function(n,s,o){if(s.indexOf(".")===-1)return At(n,s,o);let i=s.split("."),a=n;for(let l=0,c=i.length;l<c;l++)if(a=At(a,i[l],o),!a||typeof a!="object")return l<c-1?void 0:a;return a})(t,e,r)}function Te(t,e){return t===e?0:t>e?1:-1}function Pe(t,e={}){return Ot(t,Object.assign({get:$r,compare:Te},e))}var $t=(t,e,{interpret:r})=>t.value.some(n=>r(n,e)),Ir=(t,e,r)=>!$t(t,e,r),Ue=(t,e,{interpret:r})=>t.value.every(n=>r(n,e)),Nr=(t,e,{interpret:r})=>!r(t.value[0],e),ae=(t,e,{compare:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&!Array.isArray(t.value)?De(s,t.value,r):r(s,t.value)===0},Le=(t,e,r)=>!ae(t,e,r),Be=L((t,e,r)=>{let n=r.compare(e,t.value);return n===0||n===-1}),qe=L((t,e,r)=>r.compare(e,t.value)===-1),Ge=L((t,e,r)=>r.compare(e,t.value)===1),Ve=L((t,e,r)=>{let n=r.compare(e,t.value);return n===0||n===1}),ze=(t,e,{get:r})=>{if(t.field===k)return e!==void 0;let[n,s]=Et(e,t.field,r),o=i=>i==null?!!i===t.value:Ar(i,s)===t.value;return ke(n,s)?n.some(o):o(n)},Fr=L((t,e)=>typeof e=="number"&&e%t.value[0]===t.value[1]),Ye=(t,e,{get:r})=>{let[n,s]=Et(e,t.field,r),o=i=>{let a=r(i,s);return Array.isArray(a)&&a.length===t.value};return t.field!==k&&ke(n,s)?n.some(o):o(n)},We=L((t,e)=>typeof e=="string"&&t.value.test(e)),H=L((t,e,{compare:r})=>De(t.value,e,r)),Je=(t,e,r)=>!H(t,e,r),Ke=(t,e,{compare:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&t.value.every(o=>De(s,o,r))},Ze=(t,e,{interpret:r,get:n})=>{let s=n(e,t.field);return Array.isArray(s)&&s.some(o=>r(t.value,o))},Mr=(t,e)=>t.value.call(e),Cr=Object.freeze({__proto__:null,or:$t,nor:Ir,and:Ue,not:Nr,eq:ae,ne:Le,lte:Be,lt:qe,gt:Ge,gte:Ve,exists:ze,mod:Fr,size:Ye,regex:We,within:H,nin:Je,all:Ke,elemMatch:Ze,where:Mr}),ce=Object.assign({},Cr,{in:H}),vn=Pe(ce);function It(t){return t===null||typeof t!="object"?t:t instanceof Date?t.getTime():t&&typeof t.toJSON=="function"?t.toJSON():t}var Sr=(t,e)=>Te(It(t),It(e));function ue(t,e,r){let n=new ne(t),s=Pe(e,Object.assign({compare:Sr},r));if(r&&r.forPrimitives){let o={field:k},i=n.parse;n.setParse(a=>i(a,o))}return xt(n.parse,s)}var $n=ue(ie,ce),In=ue(["$and","$or"].reduce((t,e)=>(t[e]=Object.assign({},t[e],{type:"field"}),t),Object.assign({},ie,{$nor:Object.assign({},ie.$nor,{type:"field",parse:re.compound})})),ce,{forPrimitives:!0});var _t=Object.hasOwn||((t,e)=>Object.prototype.hasOwnProperty.call(t,e));function He(t){return Array.isArray(t)?t:[t]}var V="__caslSubjectType__";function Rt(t,e){if(e){if(!_t(e,V))Object.defineProperty(e,V,{value:t});else if(t!==e[V])throw new Error(`Trying to cast object to subject type ${t} but previously it was casted to ${e[V]}`)}return e}var fe=t=>{let e=typeof t;return e==="string"||e==="function"},Dt=t=>t.modelName||t.name;function _r(t){return typeof t=="string"?t:Dt(t)}function kt(t){return _t(t,V)?t[V]:Dt(t.constructor)}var Nt={function:t=>t.constructor,string:kt};function Ft(t,e,r){for(let n=r;n<e.length;n++)t.push(e[n])}function Mt(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let r=0,n=0,s=[];for(;r<t.length&&n<e.length;)t[r].priority<e[n].priority?(s.push(t[r]),r++):t[r].priority>e[n].priority?(s.push(e[n]),n++):(s.push(t[r]),r++,n++);return Ft(s,t,r),Ft(s,e,n),s}function le(t,e,r){let n=t.get(e);return n||(n=r(),t.set(e,n)),n}var Rr=t=>t;function Dr(t,e){let r;for(let n=0;n<t.length;n++){let s=e(t[n]);r&&s&&r.push(t[n]),s||(r??=t.slice(0,n))}return r||t}function kr(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')}var Qe=class{constructor(e,r,n=0){kr(e,r),this.action=r.resolveAction(e.action),this.subject=e.subject,this.inverted=!!e.inverted,this.conditions=e.conditions,this.reason=e.reason,this.origin=e,this.fields=e.fields?He(e.fields):void 0,this.priority=n,this.t=r}i(){return this.conditions&&!this.o&&(this.o=this.t.conditionsMatcher(this.conditions)),this.o}get ast(){let e=this.i();return e?e.ast:void 0}matchesConditions(e){return this.conditions?!e||fe(e)?!this.inverted:this.i()(e):!0}matchesField(e){return this.fields?e?(this.u||(this.u=this.t.fieldMatcher(this.fields)),this.u(e)):!this.inverted:!0}};function Tr(t,e){let r={value:t,prev:e,next:null};return e&&(e.next=r),r}function Pr(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t.next=t.prev=null}var Ct=()=>({rules:[],merged:!1}),St=()=>new Map,Xe=class{constructor(e=[],r={}){this.h=!1,this.l=new Map,this.p={conditionsMatcher:r.conditionsMatcher,fieldMatcher:r.fieldMatcher,resolveAction:r.resolveAction||Rr},this.$=r.anyAction||"manage",this.A=r.anySubjectType||"all",this.m=e,this.M=!!r.detectSubjectType,this.j=r.detectSubjectType||kt,this.v(e)}get rules(){return this.m}detectSubjectType(e){return fe(e)?e:e?this.j(e):this.A}update(e){let r={rules:e,ability:this,target:this};return this._("update",r),this.m=e,this.v(e),this._("updated",r),this}v(e){let r=new Map,n;for(let s=e.length-1;s>=0;s--){let o=e.length-s-1,i=new Qe(e[s],this.p,o),a=He(i.action),l=He(i.subject||this.A);!this.h&&i.fields&&(this.h=!0);for(let c=0;c<l.length;c++){let y=le(r,l[c],St);n===void 0&&(n=typeof l[c]),typeof l[c]!==n&&n!=="mixed"&&(n="mixed");for(let A=0;A<a.length;A++)le(y,a[A],Ct).rules.push(i)}}if(this.l=r,n!=="mixed"&&!this.M){let s=Nt[n]||Nt.string;this.j=s}}possibleRulesFor(e,r=this.A){if(!fe(r))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');let n=le(this.l,r,St),s=le(n,e,Ct);if(s.merged)return s.rules;let o=e!==this.$&&n.has(this.$)?n.get(this.$).rules:void 0,i=Mt(s.rules,o);return r!==this.A&&(i=Mt(i,this.possibleRulesFor(e,this.A))),s.rules=i,s.merged=!0,i}rulesFor(e,r,n){let s=this.possibleRulesFor(e,r);if(n&&typeof n!="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");return this.h?Dr(s,o=>o.matchesField(n)):s}actionsFor(e){if(!fe(e))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');let r=new Set,n=this.l.get(e);n&&Array.from(n.keys()).forEach(o=>r.add(o));let s=e!==this.A?this.l.get(this.A):void 0;return s&&Array.from(s.keys()).forEach(o=>r.add(o)),Array.from(r)}on(e,r){this.F=this.F||new Map;let n=this.F,s=n.get(e)||null,o=Tr(r,s);return n.set(e,o),()=>{let i=n.get(e);!o.next&&!o.prev&&i===o?n.delete(e):o===i&&n.set(e,o.prev),Pr(o)}}_(e,r){if(!this.F)return;let n=this.F.get(e)||null,s=[];for(;n!==null;)s.push(n.value),n=n.prev;for(let o=0;o<s.length;o++)s[o](r)}},et=class extends Xe{can(e,r,n){let s=this.relevantRuleFor(e,r,n);return!!s&&!s.inverted}relevantRuleFor(e,r,n){let s=this.detectSubjectType(r),o=this.rulesFor(e,s,n);for(let i=0,a=o.length;i<a;i++)if(o[i].matchesConditions(r))return o[i];return null}cannot(e,r,n){return!this.can(e,r,n)}},Ur={$eq:oe,$ne:Se,$lt:Me,$lte:Ce,$gt:Z,$gte:se,$in:K,$nin:Ie,$all:Ne,$size:$e,$regex:_e,$options:Re,$elemMatch:Ee,$exists:Fe},Lr={eq:ae,ne:Le,lt:qe,lte:Be,gt:Ge,gte:Ve,in:H,nin:Je,all:Ke,size:Ye,regex:We,elemMatch:Ze,exists:ze,and:Ue};var Br=ue(Ur,Lr),qr=/[-/\\^$+?.()|[\]{}]/g,Gr=/\.?\*+\.?/g,Vr=/\*+/,zr=/\./g;function Yr(t,e,r){let n=r[0]==="*"||t[0]==="."&&t[t.length-1]==="."?"+":"*",s=t.indexOf("**")===-1?"[^.]":".",o=t.replace(zr,"\\$&").replace(Vr,s+n);return e+t.length===r.length?`(?:${o})?`:o}function Wr(t,e,r){return t==="."&&(r[e-1]==="*"||r[e+1]==="*")?t:`\\${t}`}function Jr(t){let e=t.map(n=>n.replace(qr,Wr).replace(Gr,Yr)),r=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${r}$`)}var Kr=t=>{let e;return r=>(typeof e>"u"&&(e=t.every(n=>n.indexOf("*")===-1)?null:Jr(t)),e===null?t.indexOf(r)!==-1:e.test(r))};function Tt(t=[],e={}){return new et(t,Object.assign({conditionsMatcher:Br,fieldMatcher:Kr},e))}var Zr=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`,Pt=function(e){this.message=e};Pt.prototype=Object.create(Error.prototype);var tt=class extends Pt{static setDefaultMessage(e){this.P=typeof e=="string"?()=>e:e}static from(e){return new this(e)}constructor(e){super(""),this.ability=e,typeof Error.captureStackTrace=="function"&&(this.name="ForbiddenError",Error.captureStackTrace(this,this.constructor))}setMessage(e){return this.message=e,this}throwUnlessCan(e,r,n){let s=this.unlessCan(e,r,n);if(s)throw s}unlessCan(e,r,n){let s=this.ability.relevantRuleFor(e,r,n);if(s&&!s.inverted)return;this.action=e,this.subject=r,this.subjectType=_r(this.ability.detectSubjectType(r)),this.field=n;let o=s?s.reason:"";return this.message=this.message||o||this.constructor.P(this),this}};tt.P=Zr;var _n=Object.freeze({__proto__:null});function rt(t,e,r){if(t==null)return t;if(typeof t=="string"){if(t.indexOf("$principal.")!==0)return t;let s=t.slice(11).split(".").reduce((o,i)=>o==null?o:o[i],e);return s==null&&(r.unresolved=!0),s}if(Array.isArray(t))return t.map(n=>rt(n,e,r));if(typeof t=="object"){let n={};for(let s of Object.keys(t))n[s]=rt(t[s],e,r);return n}return t}function de(t,e){let r={unresolved:!1};return{conditions:rt(t,e,r),unresolved:r.unresolved}}function Ut(t,e){return de(t,e).conditions}function B(t,e){let r=G(t,e),n=[];for(let s of e.rules){if(r.indexOf(s.subject)===-1)continue;let o={action:s.actions,subject:s.resource};if(s.where){let{conditions:i,unresolved:a}=de(s.where,t);if(a)continue;o.conditions=i}n.push(o)}return n}function nt(t){return Tt(Array.isArray(t)?t:[])}function pe(t,e){return nt(B(t,e))}function $(t,e,r,n){return n==null?t.can(e,r):t.can(e,Rt(r,Object.assign({},n)))}var M={ALL:"all",NONE:"none",FIELDS:"fields",AMBIGUOUS:"ambiguous"},Lt={$in:"in",$nin:"nin",$ne:"ne",$gt:"gt",$gte:"gte",$lt:"lt",$lte:"lte"};function Hr(t){let e=[];for(let r of Object.keys(t)){let n=t[r];if(n===null||typeof n!="object"||Array.isArray(n)){e.push({field:r,op:"eq",value:n});continue}let s=Object.keys(n);if(s.length!==1||!Lt[s[0]])return null;e.push({field:r,op:Lt[s[0]],value:n[s[0]]})}return e}var Qr=(t,e)=>t==="manage"||t===e||Array.isArray(t)&&(t.indexOf(e)!==-1||t.indexOf("manage")!==-1),Xr=(t,e)=>t==="all"||t===e;function he(t,e,r,n){let s=B(t,e).filter(i=>Qr(i.action,r)&&Xr(i.subject,n));if(s.length===0)return{scope:M.NONE,clauses:[]};if(s.some(i=>!i.conditions))return{scope:M.ALL,clauses:[]};if(s.length>1)return{scope:M.AMBIGUOUS,clauses:[]};let o=Hr(s[0].conditions);return o?{scope:M.FIELDS,clauses:o}:{scope:M.AMBIGUOUS,clauses:[]}}function me(t,e){let r=t;for(let n of e)n.op==="in"?r=r.hasSome(n.field,n.value):n.op==="nin"?r=r.not(r.hasSome(n.field,n.value)):r=r[n.op](n.field,n.value);return r}var st=/export\s+const\s+([A-Za-z0-9_$]+)\s*=\s*webMethod\s*\(\s*Permissions\s*\.\s*([A-Za-z0-9_$]+)/g,en=[[/export\s*{\s*[A-Za-z0-9_$,\s]+}/,"export { x } \u2014 the call and the export must be one statement"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*Permissions\s*\[/,"Permissions['X'] \u2014 the property must be dotted and literal"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*[A-Za-z0-9_$]+\s*\(/,"a computed permission \u2014 it must be written out as Permissions.LEVEL"]];function ot(t){let e={},r=String(t||"");st.lastIndex=0;let n=st.exec(r);for(;n;)e[n[1]]=n[2],n=st.exec(r);return e}function it(t,e,r){let n=r||{},s=e&&e.api||{},o=ot(t),i=String(t||""),a=[],l=[];for(let p of Object.keys(o)){let C=s[p];C?C.permission!==o[p]&&a.push({name:p,declared:C.permission,written:o[p]}):l.push({name:p,gate:o[p]})}let c=n.complete?Object.keys(s).filter(p=>!(p in o)):[],y=[];for(let[p,C]of en)p.test(i)&&y.push(C);return{ok:a.length+l.length+c.length+y.length===0,found:o,mismatched:a,undeclared:l,missing:c,suspect:y}}function Bt(t,e,r){let n=it(t,e,r);if(n.ok)return!0;let s=[];for(let o of n.mismatched)s.push(o.name+": policy says "+o.declared+", the export says "+o.written);for(let o of n.undeclared)s.push(o.name+": gated "+o.gate+" but missing from policy.api");for(let o of n.missing)s.push(o+": declared in policy.api but not exported here");for(let o of n.suspect)s.push("unreachable export shape \u2014 "+o);throw new Error(`wix-access: web-method gates do not match the policy:
2
2
  `+s.join(`
3
- `))}var tt="0.3.2";var rt=[{action:"read",type:"Booking",object:{customerId:"m-1"}},{action:"read",type:"Booking",object:{customerId:"m-2"}},{action:"cancel",type:"Booking",object:{customerId:"m-1"}},{action:"delete",type:"Booking",object:{customerId:"m-1"}},{action:"manage",type:"Vendor",object:{_id:"v-1"}}];function kt(t){return rt.map(e=>({action:e.action,type:e.type,object:e.object,can:v(t,e.action,e.type,e.object)}))}function Dt(t,e){let{wixUsers:r,currentMember:n}=t,s=e&&e.enrich||null,o=e&&e.onError||null;return async function(){let c=null,u=!1,l=!1;try{c=r.currentUser&&r.currentUser.id||null,u=!!(r.currentUser&&r.currentUser.loggedIn)}catch(f){l=!0,o&&o("resolveCaller.id",f)}let a=[];if(c)try{a=await n.getRoles()}catch(f){l=!0,o&&o("resolveCaller.roles",f)}let d=q({kind:c?$.MEMBER:$.VISITOR,memberId:c,roles:a,unverified:l});if(d.loggedIn=u,s)try{let f=await s(d);f&&typeof f=="object"&&(d.domain=f)}catch(f){d.unverified=!0,o&&o("resolveCaller.enrich",f)}return d}}var Yr="Admin";function Pt(t,e,r){let n=r.resolveCaller,s=r.abilityFor,o=r.audit||null;function i(u,l,a,d){return o&&o({event:"access.denied",action:u,code:l,caller:a?a.memberId:null,detail:d||null}),C(l,u)}function c(u,l,a){return l==="Anyone"?null:a.memberId?l==="Admin"&&!J(a,Yr)?i(u,O.FORBIDDEN,a,{gate:l}):null:i(u,O.UNAUTHENTICATED,a)}return function(l,a,d){let f=t.api&&t.api[l]||null;if(!f)throw new Error('wix-access: web method "'+l+'" is not declared in policy.api. Add it, or the gate it runs behind is undocumented.');let p=d||{},y=f.permission,b=f.ability||null,m=p.strip||[];return async function(...x){let g=await n();if(g.unverified)return i(l,O.UNVERIFIED,g);let F=c(l,y,g);if(F)return F;let T=x.map(A=>{if(!A||typeof A!="object"||Array.isArray(A))return A;let U=Object.assign({},A);for(let Vt of m)delete U[Vt];return U}),D=null;if(b){let[A,U]=b;if(p.load){if(D=await p.load(...T),!D)return i(l,O.NOT_FOUND,g);if(!v(s(g),A,U,D))return j(l)}else if(!v(s(g),A,U))return i(l,O.FORBIDDEN,g)}return a({principal:g,subject:D},...T)}}}function Tt(t,e){let r=Object.keys(t&&t.api||{}),n=e.filter(s=>r.indexOf(s)===-1);if(n.length)throw new Error("wix-access: web methods missing from policy.api: "+n.join(", "));return!0}var Ut=100,Jr=100;function qt(t,e,r){let{items:n,auth:s}=e,o=r.abilityFor,i={query:(...a)=>s.elevate(n.query)(...a),get:(...a)=>s.elevate(n.get)(...a),insert:(...a)=>s.elevate(n.insert)(...a),update:(...a)=>s.elevate(n.update)(...a),remove:(...a)=>s.elevate(n.remove)(...a)},c=a=>{let d=t.collections&&t.collections[a]||null;return d&&d.owner?d.owner:null},u=a=>{let d=t.collections&&t.collections[a]||null;return d&&d.resource||a};async function l(a,d){let f=[],p=await a.limit(Math.min(d||Ut,Ut)).find(),y=0;for(;p;){for(let b of p.items)f.push(b);if(d&&f.length>=d)return f.slice(0,d);if(!p.hasNext||!p.hasNext()||++y>=Jr)break;p=await p.next()}return f}return{async query(a,d){let{principal:f,action:p="read",limit:y}=d,b=u(a),m=ue(f,t,p,b);if(m.scope===w.NONE)return{ok:!0,data:[],scope:m.scope};let x=i.query(a);m.scope===w.FIELDS&&(x=le(x,m.clauses));let g=await l(x,m.scope===w.AMBIGUOUS?null:y);if(m.scope!==w.AMBIGUOUS)return{ok:!0,data:g,scope:m.scope};let F=o(f),T=g.filter(D=>v(F,p,b,D));return{ok:!0,data:y?T.slice(0,y):T,scope:m.scope}},async get(a,d,f){let{principal:p,action:y="read"}=f,b=u(a),m=await i.get(a,d);return m?v(o(p),y,b,m)?{ok:!0,data:m}:j(y):j(y)},async insert(a,d,f){let{principal:p,action:y="create"}=f,b=u(a),m=c(a),x=Object.assign({},d);return m&&p.memberId&&(x[m]=p.memberId),v(o(p),y,b,x)?{ok:!0,data:await i.insert(a,x)}:C(O.FORBIDDEN,y)},async update(a,d,f,p){let{principal:y,action:b="update"}=p,m=u(a),x=await i.get(a,d);if(!x)return j(b);if(!v(o(y),b,m,x))return j(b);let g=c(a),F=Object.assign({},x,f,{_id:d});return g&&(F[g]=x[g]),{ok:!0,data:await i.update(a,F)}},async remove(a,d,f){let{principal:p,action:y="delete"}=f,b=u(a),m=await i.get(a,d);return m?v(o(p),y,b,m)?{ok:!0,data:await i.remove(a,d)}:j(y):j(y)}}}function Lt(t,e,r){K(t);let n=r||{},s=Dt(e,{enrich:n.enrich,onError:n.onError}),o=u=>ce(u,t),i=Pt(t,e,{resolveCaller:s,abilityFor:o,audit:n.audit}),c=qt(t,e,{abilityFor:o});return{policy:t,resolveCaller:s,abilityFor:o,guard:i,db:c,gateFor:u=>{let l=t.api&&t.api[u]||null;return l?l.permission:null},rulesForCaller:async()=>k(await s(),t)}}function Kr(t,e){let r=e||{},n=Object.assign({wixUsers:Bt.default,currentMember:nt.currentMember,items:zt.items,auth:Gt.auth},r.deps||{});return Lt(t,n,r)}function Zr(){return{ok:!0,side:"backend",version:tt}}async function Hr(){try{let t=await nt.currentMember.getMember();return t&&t._id||null}catch{return null}}0&&(module.exports={CASES,CODES,KIND,PACKAGE_VERSION,PolicyError,SCOPE,WHEN,abilityFor,abilityFromRules,anonymous,applyClauses,assertDeclared,assertGates,backendMemberId,backendPing,can,caseTable,createAccess,createPrincipal,deny,denyOpaque,filterFor,hasRole,isDenial,normaliseRoles,ok,parseGates,permissionFor,resolvePlaceholders,resolveSubjects,resolveWhere,rulesFor,validatePolicy,verifyGates});
3
+ `))}function qt(t,e){let r=e&&e.api||{},n=t||{},s={},o=[];for(let i of Object.keys(n)){let a=n[i],l=r[i];if(!l){o.push(i);continue}if(typeof a!="function"){o.push(i+" (not a function: "+typeof a+")");continue}try{a.permission=l.permission,s[i]=l.permission}catch(c){o.push(i+" (could not stamp: "+String(c&&c.message)+")")}}if(o.length)throw new Error("wix-access: applyGates could not gate: "+o.join(", ")+". Every exported web method must be declared in policy.api.");return s}var at="0.5.0";var ct=[{action:"read",type:"Booking",object:{customerId:"m-1"}},{action:"read",type:"Booking",object:{customerId:"m-2"}},{action:"cancel",type:"Booking",object:{customerId:"m-1"}},{action:"delete",type:"Booking",object:{customerId:"m-1"}},{action:"manage",type:"Vendor",object:{_id:"v-1"}}];function Gt(t){return ct.map(e=>({action:e.action,type:e.type,object:e.object,can:$(t,e.action,e.type,e.object)}))}function Vt(t,e){let{wixUsers:r,currentMember:n}=t,s=e&&e.enrich||null,o=e&&e.onError||null;return async function(){let a=null,l=!1,c=!1;try{a=r.currentUser&&r.currentUser.id||null,l=!!(r.currentUser&&r.currentUser.loggedIn)}catch(p){c=!0,o&&o("resolveCaller.id",p)}let y=[];if(a)try{y=await n.getRoles()}catch(p){c=!0,o&&o("resolveCaller.roles",p)}let A=Y({kind:a?R.MEMBER:R.VISITOR,memberId:a,roles:y,unverified:c});if(A.loggedIn=l,s)try{let p=await s(A);p&&typeof p=="object"&&(A.domain=p)}catch(p){A.unverified=!0,o&&o("resolveCaller.enrich",p)}return A}}var tn="Admin";function zt(t,e,r){let n=r.resolveCaller,s=r.abilityFor,o=r.audit||null;function i(l,c,y,A){return o&&o({event:"access.denied",action:l,code:c,caller:y?y.memberId:null,detail:A||null}),I(c,l)}function a(l,c,y){return c==="Anyone"?null:y.memberId?c==="Admin"&&!X(y,tn)?i(l,x.FORBIDDEN,y,{gate:c}):null:i(l,x.UNAUTHENTICATED,y)}return function(c,y,A){let p=t.api&&t.api[c]||null;if(!p)throw new Error('wix-access: web method "'+c+'" is not declared in policy.api. Add it, or the gate it runs behind is undocumented.');let C=A||{},u=p.permission,f=p.ability||null,g=C.strip||[];return async function(...O){let d=await n();if(d.unverified)return i(c,x.UNVERIFIED,d);let b=a(c,u,d);if(b)return b;let h=O.map(w=>{if(!w||typeof w!="object"||Array.isArray(w))return w;let j=Object.assign({},w);for(let E of g)delete j[E];return j}),v=null;if(f){let[w,j]=f;if(C.load){if(v=await C.load(...h),!v)return i(c,x.NOT_FOUND,d);if(!$(s(d),w,j,v))return N(c)}else if(!$(s(d),w,j))return i(c,x.FORBIDDEN,d)}return y({principal:d,subject:v},...h)}}}function Yt(t,e){let r=Object.keys(t&&t.api||{}),n=e.filter(s=>r.indexOf(s)===-1);if(n.length)throw new Error("wix-access: web methods missing from policy.api: "+n.join(", "));return!0}var Wt=100,rn=100,F="assignOwner";function Jt(t,e,r){let{items:n,auth:s}=e,o=r.abilityFor,i=r.audit||null,a=r.onError||null;function l(u){if(i)try{i(u)}catch(f){a&&a("audit",f)}}let c={query:(...u)=>s.elevate(n.query)(...u),get:(...u)=>s.elevate(n.get)(...u),insert:(...u)=>s.elevate(n.insert)(...u),update:(...u)=>s.elevate(n.update)(...u),remove:(...u)=>s.elevate(n.remove)(...u)},y=u=>{let f=t.collections&&t.collections[u]||null;return f&&f.owner?f.owner:null},A=u=>{let f=t.collections&&t.collections[u]||null;return f&&f.actor?f.actor:null},p=u=>{let f=t.collections&&t.collections[u]||null;return f&&f.resource||u};async function C(u,f){let g=[],O=await u.limit(Math.min(f||Wt,Wt)).find(),d=0;for(;O;){for(let b of O.items)g.push(b);if(f&&g.length>=f)return g.slice(0,f);if(!O.hasNext||!O.hasNext()||++d>=rn)break;O=await O.next()}return g}return{async query(u,f){let{principal:g,action:O="read",limit:d}=f,b=p(u),h=he(g,t,O,b);if(h.scope===M.NONE)return{ok:!0,data:[],scope:h.scope};let v=c.query(u);h.scope===M.FIELDS&&(v=me(v,h.clauses));let w=await C(v,h.scope===M.AMBIGUOUS?null:d);if(h.scope!==M.AMBIGUOUS)return{ok:!0,data:w,scope:h.scope};let j=o(g),E=w.filter(S=>$(j,O,b,S));return{ok:!0,data:d?E.slice(0,d):E,scope:h.scope}},async get(u,f,g){let{principal:O,action:d="read"}=g,b=p(u),h=await c.get(u,f);return h?$(o(O),d,b,h)?{ok:!0,data:h}:N(d):N(d)},async insert(u,f,g){let{principal:O,action:d="create",onBehalfOf:b,system:h=!1}=g,v=p(u),w=y(u),j=A(u),E=O.memberId||null;if(b!==void 0){if(!w)return I(x.INVALID_ARGUMENT,d,{reason:u+" declares no owner field"});if(typeof b!="string"||!b)return I(x.INVALID_ARGUMENT,d,{reason:"onBehalfOf must be a member id"})}else if(h)return I(x.INVALID_ARGUMENT,d,{reason:"system is only meaningful with onBehalfOf"});let S=Object.assign({},f),q=b!==void 0?b:E,z=q!==E;w&&(S[w]=q),j&&(S[j]=E);let lt=o(O);if(z&&!h&&!$(lt,F,v,S))return l({event:"access.denied",action:F,code:x.FORBIDDEN,caller:E,detail:{collection:u,owner:q}}),I(x.FORBIDDEN,F);if(!$(lt,d,v,S))return I(x.FORBIDDEN,d);let ye=await c.insert(u,S);return z&&l({event:"access.onBehalf",action:d,caller:E,owner:q,system:h,collection:u,id:ye&&ye._id}),{ok:!0,data:ye}},async update(u,f,g,O){let{principal:d,action:b="update"}=O;if(O.onBehalfOf!==void 0)return I(x.INVALID_ARGUMENT,b,{reason:"update never changes the owner; use transfer"});let h=p(u),v=await c.get(u,f);if(!v)return N(b);if(!$(o(d),b,h,v))return N(b);let w=y(u),j=A(u),E=Object.assign({},v,g,{_id:f});return w&&(E[w]=v[w]),j&&(E[j]=v[j]),{ok:!0,data:await c.update(u,E)}},async transfer(u,f,g,O){let{principal:d,system:b=!1}=O,h=p(u),v=y(u),w=d.memberId||null;if(!v)return I(x.INVALID_ARGUMENT,F,{reason:u+" declares no owner field"});if(g!==null&&(typeof g!="string"||!g))return I(x.INVALID_ARGUMENT,F,{reason:"newOwner must be a member id or null"});let j=await c.get(u,f);if(!j)return N(F);let E=Object.assign({},j,{_id:f,[v]:g});if(!b){let z=o(d);if(!$(z,F,h,j)||!$(z,F,h,E))return l({event:"access.denied",action:F,code:x.FORBIDDEN,caller:w,detail:{collection:u,id:f}}),N(F)}let S=j[v]===void 0?null:j[v];if(S===g)return{ok:!0,data:j};let q=await c.update(u,E);return l({event:"access.transfer",action:F,caller:w,from:S,owner:g,system:b,collection:u,id:f}),{ok:!0,data:q}},async remove(u,f,g){let{principal:O,action:d="delete"}=g,b=p(u),h=await c.get(u,f);return h?$(o(O),d,b,h)?{ok:!0,data:await c.remove(u,f)}:N(d):N(d)}}}function Kt(t,e,r){ee(t);let n=r||{},s=Vt(e,{enrich:n.enrich,onError:n.onError}),o=async()=>{let c=await s();return c.subjects=G(c,t),c},i=c=>pe(c,t),a=zt(t,e,{resolveCaller:o,abilityFor:i,audit:n.audit}),l=Jt(t,e,{abilityFor:i,audit:n.audit,onError:n.onError});return{policy:t,resolveCaller:o,abilityFor:i,guard:a,db:l,gateFor:c=>{let y=t.api&&t.api[c]||null;return y?y.permission:null},rulesForCaller:async()=>B(await o(),t)}}function nn(t,e){let r=e||{},n=Object.assign({wixUsers:Zt.default,currentMember:ut.currentMember,items:Ht.items,auth:Qt.auth},r.deps||{});return Kt(t,n,r)}function sn(){return{ok:!0,side:"backend",version:at}}async function on(){try{let t=await ut.currentMember.getMember();return t&&t._id||null}catch{return null}}0&&(module.exports={ASSIGN_OWNER,CASES,CODES,KIND,PACKAGE_VERSION,PolicyError,SCOPE,WHEN,abilityFor,abilityFromRules,anonymous,applyClauses,applyGates,assertDeclared,assertGates,backendMemberId,backendPing,can,caseTable,createAccess,createPrincipal,deny,denyOpaque,filterFor,hasRole,isDenial,normaliseRoles,ok,parseGates,permissionFor,resolvePlaceholders,resolveSubjects,resolveWhere,rulesFor,validatePolicy,verifyGates});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquisio/wix-access",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "description": "One authorization policy for Wix, serving the web-method gate, backend, database and page code. Built against measured platform behaviour.",
5
5
  "main": "./index.js",
6
6
  "types": "./types.d.ts",
@@ -8,12 +8,22 @@
8
8
  "build": "node build.mjs",
9
9
  "test": "node --test test/*.test.mjs",
10
10
  "verify": "npm run build && npm test",
11
- "prepublishOnly": "npm run verify"
11
+ "prepublishOnly": "npm run verify",
12
+ "stamp": "node ../scripts/stamp.mjs"
12
13
  },
13
14
  "exports": {
14
- ".": { "types": "./types.d.ts", "default": "./index.js" },
15
- "./backend": { "types": "./backend.d.ts", "default": "./backend.js" },
16
- "./public": { "types": "./public.d.ts", "default": "./public.js" }
15
+ ".": {
16
+ "types": "./types.d.ts",
17
+ "default": "./index.js"
18
+ },
19
+ "./backend": {
20
+ "types": "./backend.d.ts",
21
+ "default": "./backend.js"
22
+ },
23
+ "./public": {
24
+ "types": "./public.d.ts",
25
+ "default": "./public.js"
26
+ }
17
27
  },
18
28
  "files": [
19
29
  "index.js",
@@ -24,11 +34,23 @@
24
34
  "public.d.ts",
25
35
  "README.md"
26
36
  ],
27
- "engines": { "node": ">=18" },
28
- "keywords": ["wix", "velo", "blocks", "authorization", "permissions", "access-control", "casl"],
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "keywords": [
41
+ "wix",
42
+ "velo",
43
+ "blocks",
44
+ "authorization",
45
+ "permissions",
46
+ "access-control",
47
+ "casl"
48
+ ],
29
49
  "author": "Varun Dev <hello@liquis.io>",
30
50
  "license": "MIT",
31
- "publishConfig": { "access": "public" },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
32
54
  "devDependencies": {
33
55
  "@casl/ability": "^6.7.3",
34
56
  "esbuild": "^0.27.7"
package/public.js CHANGED
@@ -1,3 +1,3 @@
1
- var X=Object.defineProperty;var Rt=Object.getOwnPropertyDescriptor;var _t=Object.getOwnPropertyNames;var Pt=Object.prototype.hasOwnProperty;var Tt=(t,e)=>{for(var s in e)X(t,s,{get:e[s],enumerable:!0})},kt=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of _t(e))!Pt.call(t,n)&&n!==s&&X(t,n,{get:()=>e[n],enumerable:!(r=Rt(e,n))||r.enumerable});return t};var Dt=t=>kt(X({},"__esModule",{value:!0}),t);var Rs={};Tt(Rs,{CASES:()=>Ye,CODES:()=>E,KIND:()=>F,PACKAGE_VERSION:()=>Ge,PolicyError:()=>x,SCOPE:()=>w,WHEN:()=>y,abilityFor:()=>wt,abilityFromRules:()=>N,anonymous:()=>Ke,applyClauses:()=>It,assertGates:()=>Nt,can:()=>$,caseTable:()=>Ft,createAccess:()=>St,createPrincipal:()=>se,deny:()=>ee,denyOpaque:()=>He,filterFor:()=>Et,frontendRoleTitles:()=>Cs,hasRole:()=>Qe,isDenial:()=>k,normaliseRoles:()=>te,ok:()=>Ze,parseGates:()=>Be,permissionFor:()=>et,publicPing:()=>Ss,resolvePlaceholders:()=>$t,resolveSubjects:()=>D,resolveWhere:()=>K,rulesFor:()=>P,validatePolicy:()=>Xe,verifyGates:()=>Ve});module.exports=Dt(Rs);var Ct=require("wix-members-frontend");var E={FORBIDDEN:"FORBIDDEN",UNAUTHENTICATED:"UNAUTHENTICATED",UNVERIFIED:"UNVERIFIED",NOT_FOUND:"NOT_FOUND",INVALID_POLICY:"INVALID_POLICY",INVALID_ARGUMENT:"INVALID_ARGUMENT"},x=class extends Error{constructor(e){super(e),this.name="PolicyError",this.code=E.INVALID_POLICY}};function Ze(t){return{ok:!0,data:t===void 0?null:t}}function ee(t,e,s){let r={ok:!1,code:t||E.FORBIDDEN};return e&&(r.action=e),s&&(r.detail=s),r}var k=t=>!!t&&t.ok===!1;function He(t){return ee(E.NOT_FOUND,t)}var F={VISITOR:"visitor",MEMBER:"member",CAPABILITY:"capability",SERVICE:"service"};function te(t){if(!Array.isArray(t))return[];let e=[];for(let s of t){if(typeof s=="string"){e.push(s);continue}if(!s||typeof s!="object")continue;let r=s.title||s.name||s.roleKey;r&&e.push(r)}return e}function se(t){let e=t||{},s=e.memberId||null,r=te(e.roles);return{kind:e.kind||(s?F.MEMBER:F.VISITOR),memberId:s,roles:r,subjects:Array.isArray(e.subjects)?e.subjects.slice():[],domain:e.domain&&typeof e.domain=="object"?e.domain:{},unverified:!!e.unverified}}var Ke=()=>se({kind:F.VISITOR}),Qe=(t,e)=>t.roles.indexOf(e)!==-1;var y={ANYONE:"anyone",ANONYMOUS:"anonymous",MEMBER:"member"},m=t=>!!t&&typeof t=="object"&&!Array.isArray(t),Ut=t=>Array.isArray(t)?t:[t];function f(t,e){throw new x("policy"+t+": "+e)}function Lt(t,e){let s=".subjects."+t;m(e)||f(s,"must be an object");let n=["when","role","domain"].filter(o=>e[o]!==void 0);if(n.length===0&&f(s,'needs exactly one of when/role/domain \u2014 "{}" is ambiguous between a visitor and a member'),n.length>1&&f(s,"has "+n.join(" and ")+"; use exactly one"),e.when!==void 0){let o=[y.ANYONE,y.ANONYMOUS,y.MEMBER];o.indexOf(e.when)===-1&&f(s+".when","must be one of "+o.join(", ")+" (got "+JSON.stringify(e.when)+")")}e.role!==void 0&&typeof e.role!="string"&&f(s+".role","must be a string"),e.domain!==void 0&&typeof e.domain!="string"&&f(s+".domain","must be a string")}function qt(t,e,s){let r=".rules["+e+"]";m(t)||f(r,"must be an object"),typeof t.subject!="string"&&f(r+".subject","must be a string"),s.indexOf(t.subject)===-1&&f(r+".subject",'"'+t.subject+'" is not declared in policy.subjects'),t.actions===void 0&&f(r+".actions","is required");for(let n of Ut(t.actions))typeof n!="string"&&f(r+".actions","must be a string or an array of strings");typeof t.resource!="string"&&f(r+".resource","must be a string"),t.where!==void 0&&!m(t.where)&&f(r+".where","must be an object")}var We=["Anyone","SiteMember","Admin"];function zt(t,e,s){let r=".api."+t;m(e)||f(r,"must be an object"),We.indexOf(e.permission)===-1&&f(r+".permission","must be one of "+We.join(", ")+" (got "+JSON.stringify(e.permission)+")"),e.ability!==void 0&&((!Array.isArray(e.ability)||e.ability.length!==2)&&f(r+".ability","must be [action, resource]"),(typeof e.ability[0]!="string"||typeof e.ability[1]!="string")&&f(r+".ability","both entries must be strings")),e.subject!==void 0&&s.indexOf(e.subject)===-1&&f(r+".subject",'"'+e.subject+'" is not declared in policy.subjects')}function Xe(t){if(!m(t))throw new x("policy must be an object");m(t.subjects)||f(".subjects","is required and must be an object");let e=Object.keys(t.subjects);e.length===0&&f(".subjects","declares no subjects");for(let s of e)Lt(s,t.subjects[s]);if(Array.isArray(t.rules)||f(".rules","is required and must be an array"),t.rules.forEach((s,r)=>qt(s,r,e)),t.api!==void 0){m(t.api)||f(".api","must be an object");for(let s of Object.keys(t.api))zt(s,t.api[s],e)}return t.collections!==void 0&&!m(t.collections)&&f(".collections","must be an object"),t}function D(t,e){let s=new Set(t.subjects||[]);for(let r of Object.keys(e.subjects)){let n=e.subjects[r];(n.when===y.ANYONE||n.when===y.ANONYMOUS&&!t.memberId||n.when===y.MEMBER&&t.memberId||n.role!==void 0&&t.roles.indexOf(n.role)!==-1||n.domain!==void 0&&t.domain[n.domain])&&s.add(r)}return Array.from(s)}function et(t,e){let s=t.api&&t.api[e];return s?s.permission:null}var U=class{constructor(e,s){this.operator=e,this.value=s,Object.defineProperty(this,"t",{writable:!0})}get notes(){return this.t}addNote(e){this.t=this.t||[],this.t.push(e)}},M=class extends U{},O=class extends M{constructor(e,s){if(!Array.isArray(s))throw new Error(`"${e}" operator expects to receive an array of conditions`);super(e,s)}},b="__itself__",j=class extends U{constructor(e,s,r){super(e,r),this.field=s}},ie=new M("__null__",null),oe=Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);function Bt(t,e){return e instanceof O&&e.operator===t}function ae(t,e){return e.length===1?e[0]:new O(t,(function s(r,n,o){let i=o||[];for(let a=0,u=n.length;a<u;a++){let l=n[a];Bt(r,l)?s(r,l.value,i):i.push(l)}return i})(t,e))}var Vt=t=>t,tt=()=>Object.create(null),st=Object.defineProperty(tt(),"__@type@__",{value:"ignore value"});function Gt(t,e,s=!1){if(!t||t&&t.constructor!==Object)return!1;for(let r in t)if(oe(t,r)&&oe(e,r)&&(!s||t[r]!==st))return!0;return!1}function Yt(t){let e=[];for(let s in t)oe(t,s)&&t[s]!==st&&e.push(s);return e}function re(t,e){e!==ie&&t.push(e)}var ce=t=>ae("and",t);var L={compound(t,e,s){let r=(Array.isArray(e)?e:[e]).map(n=>s.parse(n));return new O(t.name,r)},field:(t,e,s)=>new j(t.name,s.field,e),document:(t,e)=>new M(t.name,e)},S=class{constructor(e,s=tt()){this.o=void 0,this.s=void 0,this.i=void 0,this.u=void 0,this.h=void 0,this.parse=this.parse.bind(this),this.u={operatorToConditionName:s.operatorToConditionName||Vt,defaultOperatorName:s.defaultOperatorName||"eq",mergeFinalConditions:s.mergeFinalConditions||ce},this.o=Object.keys(e).reduce((r,n)=>(r[n]=Object.assign({name:this.u.operatorToConditionName(n)},e[n]),r),{}),this.s=Object.assign({},s.fieldContext,{field:"",query:{},parse:this.parse,hasOperators:r=>Gt(r,this.o,s.useIgnoreValue)}),this.i=Object.assign({},s.documentContext,{parse:this.parse,query:{}}),this.h=s.useIgnoreValue?Yt:Object.keys}setParse(e){this.parse=e,this.s.parse=e,this.i.parse=e}parseField(e,s,r,n){let o=this.o[s];if(!o)throw new Error(`Unsupported operator "${s}"`);if(o.type!=="field")throw new Error(`Unexpected ${o.type} operator "${s}" at field level`);return this.s.field=e,this.s.query=n,this.parseInstruction(o,r,this.s)}parseInstruction(e,s,r){return typeof e.validate=="function"&&e.validate(e,s),(e.parse||L[e.type])(e,s,r)}parseFieldOperators(e,s){let r=[],n=this.h(s);for(let o=0,i=n.length;o<i;o++){let a=n[o];if(!this.o[a])throw new Error(`Field query for "${e}" may contain only operators or a plain object as a value`);re(r,this.parseField(e,a,s[a],s))}return r}parse(e){let s=[],r=this.h(e);this.i.query=e;for(let n=0,o=r.length;n<o;n++){let i=r[n],a=e[i],u=this.o[i];if(u){if(u.type!=="document"&&u.type!=="compound")throw new Error(`Cannot use parsing instruction for operator "${i}" in "document" context as it is supposed to be used in "${u.type}" context`);re(s,this.parseInstruction(u,a,this.i))}else this.s.hasOperators(a)?s.push(...this.parseFieldOperators(i,a)):re(s,this.parseField(i,this.u.defaultOperatorName,a,e))}return this.u.mergeFinalConditions(s)}};function ne(t,e){let s=t[e];if(typeof s!="function")throw new Error(`Unable to interpret "${e}" condition. Did you forget to register interpreter for it?`);return s}function Jt(t){return t.operator}function rt(t,e){let s=e,r=s&&s.getInterpreterName||Jt,n;switch(s?s.numberOfArguments:0){case 1:n=i=>{let a=r(i,s);return ne(t,a)(i,o)};break;case 3:n=(i,a,u)=>{let l=r(i,s);return ne(t,l)(i,a,u,o)};break;default:n=(i,a)=>{let u=r(i,s);return ne(t,u)(i,a,o)}}let o=Object.assign({},s,{interpret:n});return o.interpret}function nt(t,e){return(s,...r)=>{let n=t(s,...r),o=e.bind(null,n);return o.ast=n,o}}var qs=S.prototype.parseInstruction;function ot(t,e){if(!Array.isArray(e))throw new Error(`"${t.name}" expects value to be an array`)}function it(t,e){if(ot(t,e),!e.length)throw new Error(`"${t.name}" expects to have at least one element in array`)}var ue=t=>(e,s)=>{if(typeof s!==t)throw new Error(`"${e.name}" expects value to be a "${t}"`)},at={type:"compound",validate:it,parse(t,e,{parse:s}){let r=e.map(n=>s(n));return ae(t.name,r)}},Zt=at,Ht={type:"compound",validate:it},Kt={type:"field",validate(t,e){if(!(e&&(e instanceof RegExp||e.constructor===Object)))throw new Error(`"${t.name}" expects to receive either regular expression or object of field operators`)},parse(t,e,s){let r=e instanceof RegExp?new j("regex",s.field,e):s.parse(e,s);return new O(t.name,[r])}},le={type:"field",validate(t,e){if(!e||e.constructor!==Object)throw new Error(`"${t.name}" expects to receive an object with nested query or field level operators`)},parse(t,e,{parse:s,field:r,hasOperators:n}){let o=n(e)?s(e,{field:b}):s(e);return new j(t.name,r,o)}},fe={type:"field",validate:ue("number")},C={type:"field",validate:ot},pe=C,de=C,Qt={type:"field",validate(t,e){if(!Array.isArray(e)||e.length!==2)throw new Error(`"${t.name}" expects an array with 2 numeric elements`)}},he={type:"field",validate:ue("boolean")},z={type:"field",validate:function(t,e){if(!(typeof e=="string"||typeof e=="number"||e instanceof Date))throw new Error(`"${t.name}" expects value to be comparable (i.e., string, number or date)`)}},R=z,me=R,ye=R,B={type:"field"},be=B,ge={type:"field",validate(t,e){if(!(e instanceof RegExp)&&typeof e!="string")throw new Error(`"${t.name}" expects value to be a regular expression or a string that represents regular expression`)},parse(t,e,s){let r=typeof e=="string"?new RegExp(e,s.query.$options||""):e;return new j(t.name,s.field,r)}},xe={type:"field",parse:()=>ie},Wt={type:"document",validate:ue("function")},Xt=Object.freeze({__proto__:null,$and:at,$or:Zt,$nor:Ht,$not:Kt,$elemMatch:le,$size:fe,$in:C,$nin:pe,$all:de,$mod:Qt,$exists:he,$gte:z,$gt:R,$lt:me,$lte:ye,$eq:B,$ne:be,$regex:ge,$options:xe,$where:Wt}),q=class extends S{constructor(e){super(e,{defaultOperatorName:"$eq",operatorToConditionName:s=>s.slice(1)})}parse(e,s){return s&&s.field?ce(this.parseFieldOperators(s.field,e)):super.parse(e)}},V=Xt;function Oe(t,e,s){for(let r=0,n=t.length;r<n;r++)if(s(t[r],e)===0)return!0;return!1}function je(t,e){return Array.isArray(t)&&Number.isNaN(Number(e))}function ct(t,e,s){if(!je(t,e))return s(t,e);let r=[];for(let n=0;n<t.length;n++){let o=s(t[n],e);o!==void 0&&(r=r.concat(o))}return r}function v(t){return(e,s,r)=>{let n=r.get(s,e.field);return Array.isArray(n)?n.some(o=>t(e,o,r)):t(e,n,r)}}var es=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty),ts=(t,e)=>t[e];function ut(t,e,s){let r=e.lastIndexOf(".");return r===-1?[t,e]:[s(t,e.slice(0,r)),e.slice(r+1)]}function ss(t,e,s=ts){if(e===b)return t;if(!t)throw new Error(`Unable to get field "${e}" out of ${String(t)}.`);return(function(r,n,o){if(n.indexOf(".")===-1)return ct(r,n,o);let i=n.split("."),a=r;for(let u=0,l=i.length;u<l;u++)if(a=ct(a,i[u],o),!a||typeof a!="object")return u<l-1?void 0:a;return a})(t,e,s)}function ve(t,e){return t===e?0:t>e?1:-1}function $e(t,e={}){return rt(t,Object.assign({get:ss,compare:ve},e))}var lt=(t,e,{interpret:s})=>t.value.some(r=>s(r,e)),rs=(t,e,s)=>!lt(t,e,s),we=(t,e,{interpret:s})=>t.value.every(r=>s(r,e)),ns=(t,e,{interpret:s})=>!s(t.value[0],e),G=(t,e,{compare:s,get:r})=>{let n=r(e,t.field);return Array.isArray(n)&&!Array.isArray(t.value)?Oe(n,t.value,s):s(n,t.value)===0},Ae=(t,e,s)=>!G(t,e,s),Ee=v((t,e,s)=>{let r=s.compare(e,t.value);return r===0||r===-1}),Ie=v((t,e,s)=>s.compare(e,t.value)===-1),Ne=v((t,e,s)=>s.compare(e,t.value)===1),Fe=v((t,e,s)=>{let r=s.compare(e,t.value);return r===0||r===1}),Me=(t,e,{get:s})=>{if(t.field===b)return e!==void 0;let[r,n]=ut(e,t.field,s),o=i=>i==null?!!i===t.value:es(i,n)===t.value;return je(r,n)?r.some(o):o(r)},os=v((t,e)=>typeof e=="number"&&e%t.value[0]===t.value[1]),Se=(t,e,{get:s})=>{let[r,n]=ut(e,t.field,s),o=i=>{let a=s(i,n);return Array.isArray(a)&&a.length===t.value};return t.field!==b&&je(r,n)?r.some(o):o(r)},Ce=v((t,e)=>typeof e=="string"&&t.value.test(e)),_=v((t,e,{compare:s})=>Oe(t.value,e,s)),Re=(t,e,s)=>!_(t,e,s),_e=(t,e,{compare:s,get:r})=>{let n=r(e,t.field);return Array.isArray(n)&&t.value.every(o=>Oe(n,o,s))},Pe=(t,e,{interpret:s,get:r})=>{let n=r(e,t.field);return Array.isArray(n)&&n.some(o=>s(t.value,o))},is=(t,e)=>t.value.call(e),as=Object.freeze({__proto__:null,or:lt,nor:rs,and:we,not:ns,eq:G,ne:Ae,lte:Ee,lt:Ie,gt:Ne,gte:Fe,exists:Me,mod:os,size:Se,regex:Ce,within:_,nin:Re,all:_e,elemMatch:Pe,where:is}),Y=Object.assign({},as,{in:_}),Js=$e(Y);function ft(t){return t===null||typeof t!="object"?t:t instanceof Date?t.getTime():t&&typeof t.toJSON=="function"?t.toJSON():t}var cs=(t,e)=>ve(ft(t),ft(e));function J(t,e,s){let r=new q(t),n=$e(e,Object.assign({compare:cs},s));if(s&&s.forPrimitives){let o={field:b},i=r.parse;r.setParse(a=>i(a,o))}return nt(r.parse,n)}var Ws=J(V,Y),Xs=J(["$and","$or"].reduce((t,e)=>(t[e]=Object.assign({},t[e],{type:"field"}),t),Object.assign({},V,{$nor:Object.assign({},V.$nor,{type:"field",parse:L.compound})})),Y,{forPrimitives:!0});var bt=Object.hasOwn||((t,e)=>Object.prototype.hasOwnProperty.call(t,e));function Te(t){return Array.isArray(t)?t:[t]}var I="__caslSubjectType__";function gt(t,e){if(e){if(!bt(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}var H=t=>{let e=typeof t;return e==="string"||e==="function"},xt=t=>t.modelName||t.name;function us(t){return typeof t=="string"?t:xt(t)}function Ot(t){return bt(t,I)?t[I]:xt(t.constructor)}var pt={function:t=>t.constructor,string:Ot};function dt(t,e,s){for(let r=s;r<e.length;r++)t.push(e[r])}function ht(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let s=0,r=0,n=[];for(;s<t.length&&r<e.length;)t[s].priority<e[r].priority?(n.push(t[s]),s++):t[s].priority>e[r].priority?(n.push(e[r]),r++):(n.push(t[s]),s++,r++);return dt(n,t,s),dt(n,e,r),n}function Z(t,e,s){let r=t.get(e);return r||(r=s(),t.set(e,r)),r}var ls=t=>t;function fs(t,e){let s;for(let r=0;r<t.length;r++){let n=e(t[r]);s&&n&&s.push(t[r]),n||(s??(s=t.slice(0,r)))}return s||t}function ps(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')}var ke=class{constructor(e,s,r=0){ps(e,s),this.action=s.resolveAction(e.action),this.subject=e.subject,this.inverted=!!e.inverted,this.conditions=e.conditions,this.reason=e.reason,this.origin=e,this.fields=e.fields?Te(e.fields):void 0,this.priority=r,this.t=s}i(){return this.conditions&&!this.o&&(this.o=this.t.conditionsMatcher(this.conditions)),this.o}get ast(){let e=this.i();return e?e.ast:void 0}matchesConditions(e){return this.conditions?!e||H(e)?!this.inverted:this.i()(e):!0}matchesField(e){return this.fields?e?(this.u||(this.u=this.t.fieldMatcher(this.fields)),this.u(e)):!this.inverted:!0}};function ds(t,e){let s={value:t,prev:e,next:null};return e&&(e.next=s),s}function hs(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t.next=t.prev=null}var mt=()=>({rules:[],merged:!1}),yt=()=>new Map,De=class{constructor(e=[],s={}){this.h=!1,this.l=new Map,this.p={conditionsMatcher:s.conditionsMatcher,fieldMatcher:s.fieldMatcher,resolveAction:s.resolveAction||ls},this.$=s.anyAction||"manage",this.A=s.anySubjectType||"all",this.m=e,this.M=!!s.detectSubjectType,this.j=s.detectSubjectType||Ot,this.v(e)}get rules(){return this.m}detectSubjectType(e){return H(e)?e:e?this.j(e):this.A}update(e){let s={rules:e,ability:this,target:this};return this._("update",s),this.m=e,this.v(e),this._("updated",s),this}v(e){let s=new Map,r;for(let n=e.length-1;n>=0;n--){let o=e.length-n-1,i=new ke(e[n],this.p,o),a=Te(i.action),u=Te(i.subject||this.A);!this.h&&i.fields&&(this.h=!0);for(let l=0;l<u.length;l++){let h=Z(s,u[l],yt);r===void 0&&(r=typeof u[l]),typeof u[l]!==r&&r!=="mixed"&&(r="mixed");for(let A=0;A<a.length;A++)Z(h,a[A],mt).rules.push(i)}}if(this.l=s,r!=="mixed"&&!this.M){let n=pt[r]||pt.string;this.j=n}}possibleRulesFor(e,s=this.A){if(!H(s))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');let r=Z(this.l,s,yt),n=Z(r,e,mt);if(n.merged)return n.rules;let o=e!==this.$&&r.has(this.$)?r.get(this.$).rules:void 0,i=ht(n.rules,o);return s!==this.A&&(i=ht(i,this.possibleRulesFor(e,this.A))),n.rules=i,n.merged=!0,i}rulesFor(e,s,r){let n=this.possibleRulesFor(e,s);if(r&&typeof r!="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");return this.h?fs(n,o=>o.matchesField(r)):n}actionsFor(e){if(!H(e))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');let s=new Set,r=this.l.get(e);r&&Array.from(r.keys()).forEach(o=>s.add(o));let n=e!==this.A?this.l.get(this.A):void 0;return n&&Array.from(n.keys()).forEach(o=>s.add(o)),Array.from(s)}on(e,s){this.F=this.F||new Map;let r=this.F,n=r.get(e)||null,o=ds(s,n);return r.set(e,o),()=>{let i=r.get(e);!o.next&&!o.prev&&i===o?r.delete(e):o===i&&r.set(e,o.prev),hs(o)}}_(e,s){if(!this.F)return;let r=this.F.get(e)||null,n=[];for(;r!==null;)n.push(r.value),r=r.prev;for(let o=0;o<n.length;o++)n[o](s)}},Ue=class extends De{can(e,s,r){let n=this.relevantRuleFor(e,s,r);return!!n&&!n.inverted}relevantRuleFor(e,s,r){let n=this.detectSubjectType(s),o=this.rulesFor(e,n,r);for(let i=0,a=o.length;i<a;i++)if(o[i].matchesConditions(s))return o[i];return null}cannot(e,s,r){return!this.can(e,s,r)}},ms={$eq:B,$ne:be,$lt:me,$lte:ye,$gt:R,$gte:z,$in:C,$nin:pe,$all:de,$size:fe,$regex:ge,$options:xe,$elemMatch:le,$exists:he},ys={eq:G,ne:Ae,lt:Ie,lte:Ee,gt:Ne,gte:Fe,in:_,nin:Re,all:_e,size:Se,regex:Ce,elemMatch:Pe,exists:Me,and:we};var bs=J(ms,ys),gs=/[-/\\^$+?.()|[\]{}]/g,xs=/\.?\*+\.?/g,Os=/\*+/,js=/\./g;function vs(t,e,s){let r=s[0]==="*"||t[0]==="."&&t[t.length-1]==="."?"+":"*",n=t.indexOf("**")===-1?"[^.]":".",o=t.replace(js,"\\$&").replace(Os,n+r);return e+t.length===s.length?`(?:${o})?`:o}function $s(t,e,s){return t==="."&&(s[e-1]==="*"||s[e+1]==="*")?t:`\\${t}`}function ws(t){let e=t.map(r=>r.replace(gs,$s).replace(xs,vs)),s=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${s}$`)}var As=t=>{let e;return s=>(typeof e>"u"&&(e=t.every(r=>r.indexOf("*")===-1)?null:ws(t)),e===null?t.indexOf(s)!==-1:e.test(s))};function jt(t=[],e={}){return new Ue(t,Object.assign({conditionsMatcher:bs,fieldMatcher:As},e))}var Es=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`,vt=function(e){this.message=e};vt.prototype=Object.create(Error.prototype);var Le=class extends vt{static setDefaultMessage(e){this.P=typeof e=="string"?()=>e:e}static from(e){return new this(e)}constructor(e){super(""),this.ability=e,typeof Error.captureStackTrace=="function"&&(this.name="ForbiddenError",Error.captureStackTrace(this,this.constructor))}setMessage(e){return this.message=e,this}throwUnlessCan(e,s,r){let n=this.unlessCan(e,s,r);if(n)throw n}unlessCan(e,s,r){let n=this.ability.relevantRuleFor(e,s,r);if(n&&!n.inverted)return;this.action=e,this.subject=s,this.subjectType=us(this.ability.detectSubjectType(s)),this.field=r;let o=n?n.reason:"";return this.message=this.message||o||this.constructor.P(this),this}};Le.P=Es;var or=Object.freeze({__proto__:null});function qe(t,e,s){if(t==null)return t;if(typeof t=="string"){if(t.indexOf("$principal.")!==0)return t;let n=t.slice(11).split(".").reduce((o,i)=>o==null?o:o[i],e);return n==null&&(s.unresolved=!0),n}if(Array.isArray(t))return t.map(r=>qe(r,e,s));if(typeof t=="object"){let r={};for(let n of Object.keys(t))r[n]=qe(t[n],e,s);return r}return t}function K(t,e){let s={unresolved:!1};return{conditions:qe(t,e,s),unresolved:s.unresolved}}function $t(t,e){return K(t,e).conditions}function P(t,e){let s=D(t,e),r=[];for(let n of e.rules){if(s.indexOf(n.subject)===-1)continue;let o={action:n.actions,subject:n.resource};if(n.where){let{conditions:i,unresolved:a}=K(n.where,t);if(a)continue;o.conditions=i}r.push(o)}return r}function N(t){return jt(Array.isArray(t)?t:[])}function wt(t,e){return N(P(t,e))}function $(t,e,s,r){return r==null?t.can(e,s):t.can(e,gt(s,Object.assign({},r)))}var w={ALL:"all",NONE:"none",FIELDS:"fields",AMBIGUOUS:"ambiguous"},At={$in:"in",$nin:"nin",$ne:"ne",$gt:"gt",$gte:"gte",$lt:"lt",$lte:"lte"};function Is(t){let e=[];for(let s of Object.keys(t)){let r=t[s];if(r===null||typeof r!="object"||Array.isArray(r)){e.push({field:s,op:"eq",value:r});continue}let n=Object.keys(r);if(n.length!==1||!At[n[0]])return null;e.push({field:s,op:At[n[0]],value:r[n[0]]})}return e}var Ns=(t,e)=>t==="manage"||t===e||Array.isArray(t)&&(t.indexOf(e)!==-1||t.indexOf("manage")!==-1),Fs=(t,e)=>t==="all"||t===e;function Et(t,e,s,r){let n=P(t,e).filter(i=>Ns(i.action,s)&&Fs(i.subject,r));if(n.length===0)return{scope:w.NONE,clauses:[]};if(n.some(i=>!i.conditions))return{scope:w.ALL,clauses:[]};if(n.length>1)return{scope:w.AMBIGUOUS,clauses:[]};let o=Is(n[0].conditions);return o?{scope:w.FIELDS,clauses:o}:{scope:w.AMBIGUOUS,clauses:[]}}function It(t,e){let s=t;for(let r of e)r.op==="in"?s=s.hasSome(r.field,r.value):r.op==="nin"?s=s.not(s.hasSome(r.field,r.value)):s=s[r.op](r.field,r.value);return s}var ze=/export\s+const\s+([A-Za-z0-9_$]+)\s*=\s*webMethod\s*\(\s*Permissions\s*\.\s*([A-Za-z0-9_$]+)/g,Ms=[[/export\s*{\s*[A-Za-z0-9_$,\s]+}/,"export { x } \u2014 the call and the export must be one statement"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*Permissions\s*\[/,"Permissions['X'] \u2014 the property must be dotted and literal"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*[A-Za-z0-9_$]+\s*\(/,"a computed permission \u2014 it must be written out as Permissions.LEVEL"]];function Be(t){let e={},s=String(t||"");ze.lastIndex=0;let r=ze.exec(s);for(;r;)e[r[1]]=r[2],r=ze.exec(s);return e}function Ve(t,e,s){let r=s||{},n=e&&e.api||{},o=Be(t),i=String(t||""),a=[],u=[];for(let p of Object.keys(o)){let c=n[p];c?c.permission!==o[p]&&a.push({name:p,declared:c.permission,written:o[p]}):u.push({name:p,gate:o[p]})}let l=r.complete?Object.keys(n).filter(p=>!(p in o)):[],h=[];for(let[p,c]of Ms)p.test(i)&&h.push(c);return{ok:a.length+u.length+l.length+h.length===0,found:o,mismatched:a,undeclared:u,missing:l,suspect:h}}function Nt(t,e,s){let r=Ve(t,e,s);if(r.ok)return!0;let n=[];for(let o of r.mismatched)n.push(o.name+": policy says "+o.declared+", the export says "+o.written);for(let o of r.undeclared)n.push(o.name+": gated "+o.gate+" but missing from policy.api");for(let o of r.missing)n.push(o+": declared in policy.api but not exported here");for(let o of r.suspect)n.push("unreachable export shape \u2014 "+o);throw new Error(`wix-access: web-method gates do not match the policy:
2
- `+n.join(`
3
- `))}var Ge="0.3.2";var Ye=[{action:"read",type:"Booking",object:{customerId:"m-1"}},{action:"read",type:"Booking",object:{customerId:"m-2"}},{action:"cancel",type:"Booking",object:{customerId:"m-1"}},{action:"delete",type:"Booking",object:{customerId:"m-1"}},{action:"manage",type:"Vendor",object:{_id:"v-1"}}];function Ft(t){return Ye.map(e=>({action:e.action,type:e.type,object:e.object,can:$(t,e.action,e.type,e.object)}))}var Q=N([]),Mt="wix-access: createAccess({ fetchRules }) needs your web method, e.g. import { getMyAbilities } from 'backend/access.web'. The package cannot import it for you \u2014 that specifier only resolves inside your project. If it is imported and still not a function, build the kit inside onReady and pass an arrow: fetchRules: (...a) => getMyAbilities(...a).";function St(t){let e=t||{},s=e.fetchRules,r=e.onError||null,n=typeof s!="function",o=Q,i=[],a=!1,u=!1,l=null,h=null;async function A(){if(n)return i=[],o=Q,u=!0,l=Mt,a=!0,r&&r(new Error(Mt)),p;try{let c=await s();if(k(c))return i=[],o=Q,u=!0,l="rules refused: "+(c.code||"FORBIDDEN"),a=!0,r&&r(new Error(l)),p;i=Array.isArray(c)?c:[],o=N(i),u=!1}catch(c){i=[],o=Q,u=!0,l=String(c&&c.message||c),r&&r(c)}return a=!0,p}let p={ready(){return a?Promise.resolve(p):(h||(h=A().then(c=>(h=null,c))),h)},refresh(){return a=!1,u=!1,l=null,h=null,p.ready()},can:(c,d,g)=>$(o,c,d,g),cannot:(c,d,g)=>!$(o,c,d,g),rules:()=>i.slice(),get loaded(){return a},get failed(){return u},get reason(){return l},guard(c,d,g,T,W){let Je=p.can(d,g,T);return p.apply(c,Je,W),Je},apply(c,d,g){if(!c)return d;let T=g||"hide";try{T==="disable"?d&&c.enable?c.enable():!d&&c.disable&&c.disable():T==="collapse"?d&&c.expand?c.expand():!d&&c.collapse&&c.collapse():d&&c.show?c.show():!d&&c.hide&&c.hide()}catch(W){r&&r(W)}return d}};return p}function Ss(){return{ok:!0,side:"public",version:Ge}}async function Cs(){try{return(await Ct.currentMember.getRoles()).map(e=>e.title)}catch{return[]}}0&&(module.exports={CASES,CODES,KIND,PACKAGE_VERSION,PolicyError,SCOPE,WHEN,abilityFor,abilityFromRules,anonymous,applyClauses,assertGates,can,caseTable,createAccess,createPrincipal,deny,denyOpaque,filterFor,frontendRoleTitles,hasRole,isDenial,normaliseRoles,ok,parseGates,permissionFor,publicPing,resolvePlaceholders,resolveSubjects,resolveWhere,rulesFor,validatePolicy,verifyGates});
1
+ var X=Object.defineProperty;var Rt=Object.getOwnPropertyDescriptor;var Tt=Object.getOwnPropertyNames;var Pt=Object.prototype.hasOwnProperty;var kt=(t,e)=>{for(var n in e)X(t,n,{get:e[n],enumerable:!0})},Dt=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Tt(e))!Pt.call(t,r)&&r!==n&&X(t,r,{get:()=>e[r],enumerable:!(s=Rt(e,r))||s.enumerable});return t};var Lt=t=>Dt(X({},"__esModule",{value:!0}),t);var kn={};kt(kn,{CASES:()=>Ye,CODES:()=>E,KIND:()=>F,PACKAGE_VERSION:()=>Ge,PolicyError:()=>x,SCOPE:()=>$,WHEN:()=>y,abilityFor:()=>$t,abilityFromRules:()=>N,anonymous:()=>Ke,applyClauses:()=>It,applyGates:()=>Ft,assertGates:()=>Nt,can:()=>w,caseTable:()=>Mt,createAccess:()=>Ct,createPrincipal:()=>ne,deny:()=>ee,denyOpaque:()=>He,filterFor:()=>Et,frontendRoleTitles:()=>Pn,hasRole:()=>Qe,isDenial:()=>k,normaliseRoles:()=>te,ok:()=>Ze,parseGates:()=>Be,permissionFor:()=>et,publicPing:()=>Tn,resolvePlaceholders:()=>wt,resolveSubjects:()=>D,resolveWhere:()=>K,rulesFor:()=>T,validatePolicy:()=>Xe,verifyGates:()=>Ve});module.exports=Lt(kn);var _t=require("wix-members-frontend");var E={FORBIDDEN:"FORBIDDEN",UNAUTHENTICATED:"UNAUTHENTICATED",UNVERIFIED:"UNVERIFIED",NOT_FOUND:"NOT_FOUND",INVALID_POLICY:"INVALID_POLICY",INVALID_ARGUMENT:"INVALID_ARGUMENT"},x=class extends Error{constructor(e){super(e),this.name="PolicyError",this.code=E.INVALID_POLICY}};function Ze(t){return{ok:!0,data:t===void 0?null:t}}function ee(t,e,n){let s={ok:!1,code:t||E.FORBIDDEN};return e&&(s.action=e),n&&(s.detail=n),s}var k=t=>!!t&&t.ok===!1;function He(t){return ee(E.NOT_FOUND,t)}var F={VISITOR:"visitor",MEMBER:"member",CAPABILITY:"capability",SERVICE:"service"};function te(t){if(!Array.isArray(t))return[];let e=[];for(let n of t){if(typeof n=="string"){e.push(n);continue}if(!n||typeof n!="object")continue;let s=n.title||n.name||n.roleKey;s&&e.push(s)}return e}function ne(t){let e=t||{},n=e.memberId||null,s=te(e.roles);return{kind:e.kind||(n?F.MEMBER:F.VISITOR),memberId:n,roles:s,subjects:Array.isArray(e.subjects)?e.subjects.slice():[],domain:e.domain&&typeof e.domain=="object"?e.domain:{},unverified:!!e.unverified}}var Ke=()=>ne({kind:F.VISITOR}),Qe=(t,e)=>t.roles.indexOf(e)!==-1;var y={ANYONE:"anyone",ANONYMOUS:"anonymous",MEMBER:"member"},m=t=>!!t&&typeof t=="object"&&!Array.isArray(t),Ut=t=>Array.isArray(t)?t:[t];function f(t,e){throw new x("policy"+t+": "+e)}function qt(t,e){let n=".subjects."+t;m(e)||f(n,"must be an object");let r=["when","role","domain"].filter(o=>e[o]!==void 0);if(r.length===0&&f(n,'needs exactly one of when/role/domain \u2014 "{}" is ambiguous between a visitor and a member'),r.length>1&&f(n,"has "+r.join(" and ")+"; use exactly one"),e.when!==void 0){let o=[y.ANYONE,y.ANONYMOUS,y.MEMBER];o.indexOf(e.when)===-1&&f(n+".when","must be one of "+o.join(", ")+" (got "+JSON.stringify(e.when)+")")}e.role!==void 0&&typeof e.role!="string"&&f(n+".role","must be a string"),e.domain!==void 0&&typeof e.domain!="string"&&f(n+".domain","must be a string")}function zt(t,e,n){let s=".rules["+e+"]";m(t)||f(s,"must be an object"),typeof t.subject!="string"&&f(s+".subject","must be a string"),n.indexOf(t.subject)===-1&&f(s+".subject",'"'+t.subject+'" is not declared in policy.subjects'),t.actions===void 0&&f(s+".actions","is required");for(let r of Ut(t.actions))typeof r!="string"&&f(s+".actions","must be a string or an array of strings");typeof t.resource!="string"&&f(s+".resource","must be a string"),t.where!==void 0&&!m(t.where)&&f(s+".where","must be an object")}var We=["Anyone","SiteMember","Admin"];function Bt(t,e,n){let s=".api."+t;m(e)||f(s,"must be an object"),We.indexOf(e.permission)===-1&&f(s+".permission","must be one of "+We.join(", ")+" (got "+JSON.stringify(e.permission)+")"),e.ability!==void 0&&((!Array.isArray(e.ability)||e.ability.length!==2)&&f(s+".ability","must be [action, resource]"),(typeof e.ability[0]!="string"||typeof e.ability[1]!="string")&&f(s+".ability","both entries must be strings")),e.subject!==void 0&&n.indexOf(e.subject)===-1&&f(s+".subject",'"'+e.subject+'" is not declared in policy.subjects')}var Vt=["resource","owner","actor","tenant","profile"];function Gt(t,e){let n=".collections."+t;m(e)||f(n,"must be an object");for(let s of Vt)e[s]!==void 0&&(typeof e[s]!="string"||!e[s])&&f(n+"."+s,"must be a non-empty string");e.owner!==void 0&&e.owner===e.actor&&f(n,'owner and actor must be different fields (both are "'+e.owner+'")')}function Xe(t){if(!m(t))throw new x("policy must be an object");m(t.subjects)||f(".subjects","is required and must be an object");let e=Object.keys(t.subjects);e.length===0&&f(".subjects","declares no subjects");for(let n of e)qt(n,t.subjects[n]);if(Array.isArray(t.rules)||f(".rules","is required and must be an array"),t.rules.forEach((n,s)=>zt(n,s,e)),t.api!==void 0){m(t.api)||f(".api","must be an object");for(let n of Object.keys(t.api))Bt(n,t.api[n],e)}if(t.collections!==void 0){m(t.collections)||f(".collections","must be an object");for(let n of Object.keys(t.collections))Gt(n,t.collections[n])}return t}function D(t,e){let n=new Set(t.subjects||[]);for(let s of Object.keys(e.subjects)){let r=e.subjects[s];(r.when===y.ANYONE||r.when===y.ANONYMOUS&&!t.memberId||r.when===y.MEMBER&&t.memberId||r.role!==void 0&&t.roles.indexOf(r.role)!==-1||r.domain!==void 0&&t.domain[r.domain])&&n.add(s)}return Array.from(n)}function et(t,e){let n=t.api&&t.api[e];return n?n.permission:null}var L=class{constructor(e,n){this.operator=e,this.value=n,Object.defineProperty(this,"t",{writable:!0})}get notes(){return this.t}addNote(e){this.t=this.t||[],this.t.push(e)}},M=class extends L{},O=class extends M{constructor(e,n){if(!Array.isArray(n))throw new Error(`"${e}" operator expects to receive an array of conditions`);super(e,n)}},b="__itself__",j=class extends L{constructor(e,n,s){super(e,s),this.field=n}},ie=new M("__null__",null),oe=Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);function Yt(t,e){return e instanceof O&&e.operator===t}function ae(t,e){return e.length===1?e[0]:new O(t,(function n(s,r,o){let i=o||[];for(let a=0,u=r.length;a<u;a++){let l=r[a];Yt(s,l)?n(s,l.value,i):i.push(l)}return i})(t,e))}var Jt=t=>t,tt=()=>Object.create(null),nt=Object.defineProperty(tt(),"__@type@__",{value:"ignore value"});function Zt(t,e,n=!1){if(!t||t&&t.constructor!==Object)return!1;for(let s in t)if(oe(t,s)&&oe(e,s)&&(!n||t[s]!==nt))return!0;return!1}function Ht(t){let e=[];for(let n in t)oe(t,n)&&t[n]!==nt&&e.push(n);return e}function se(t,e){e!==ie&&t.push(e)}var ce=t=>ae("and",t);var U={compound(t,e,n){let s=(Array.isArray(e)?e:[e]).map(r=>n.parse(r));return new O(t.name,s)},field:(t,e,n)=>new j(t.name,n.field,e),document:(t,e)=>new M(t.name,e)},S=class{constructor(e,n=tt()){this.o=void 0,this.s=void 0,this.i=void 0,this.u=void 0,this.h=void 0,this.parse=this.parse.bind(this),this.u={operatorToConditionName:n.operatorToConditionName||Jt,defaultOperatorName:n.defaultOperatorName||"eq",mergeFinalConditions:n.mergeFinalConditions||ce},this.o=Object.keys(e).reduce((s,r)=>(s[r]=Object.assign({name:this.u.operatorToConditionName(r)},e[r]),s),{}),this.s=Object.assign({},n.fieldContext,{field:"",query:{},parse:this.parse,hasOperators:s=>Zt(s,this.o,n.useIgnoreValue)}),this.i=Object.assign({},n.documentContext,{parse:this.parse,query:{}}),this.h=n.useIgnoreValue?Ht:Object.keys}setParse(e){this.parse=e,this.s.parse=e,this.i.parse=e}parseField(e,n,s,r){let o=this.o[n];if(!o)throw new Error(`Unsupported operator "${n}"`);if(o.type!=="field")throw new Error(`Unexpected ${o.type} operator "${n}" at field level`);return this.s.field=e,this.s.query=r,this.parseInstruction(o,s,this.s)}parseInstruction(e,n,s){return typeof e.validate=="function"&&e.validate(e,n),(e.parse||U[e.type])(e,n,s)}parseFieldOperators(e,n){let s=[],r=this.h(n);for(let o=0,i=r.length;o<i;o++){let a=r[o];if(!this.o[a])throw new Error(`Field query for "${e}" may contain only operators or a plain object as a value`);se(s,this.parseField(e,a,n[a],n))}return s}parse(e){let n=[],s=this.h(e);this.i.query=e;for(let r=0,o=s.length;r<o;r++){let i=s[r],a=e[i],u=this.o[i];if(u){if(u.type!=="document"&&u.type!=="compound")throw new Error(`Cannot use parsing instruction for operator "${i}" in "document" context as it is supposed to be used in "${u.type}" context`);se(n,this.parseInstruction(u,a,this.i))}else this.s.hasOperators(a)?n.push(...this.parseFieldOperators(i,a)):se(n,this.parseField(i,this.u.defaultOperatorName,a,e))}return this.u.mergeFinalConditions(n)}};function re(t,e){let n=t[e];if(typeof n!="function")throw new Error(`Unable to interpret "${e}" condition. Did you forget to register interpreter for it?`);return n}function Kt(t){return t.operator}function st(t,e){let n=e,s=n&&n.getInterpreterName||Kt,r;switch(n?n.numberOfArguments:0){case 1:r=i=>{let a=s(i,n);return re(t,a)(i,o)};break;case 3:r=(i,a,u)=>{let l=s(i,n);return re(t,l)(i,a,u,o)};break;default:r=(i,a)=>{let u=s(i,n);return re(t,u)(i,a,o)}}let o=Object.assign({},n,{interpret:r});return o.interpret}function rt(t,e){return(n,...s)=>{let r=t(n,...s),o=e.bind(null,r);return o.ast=r,o}}var Gn=S.prototype.parseInstruction;function ot(t,e){if(!Array.isArray(e))throw new Error(`"${t.name}" expects value to be an array`)}function it(t,e){if(ot(t,e),!e.length)throw new Error(`"${t.name}" expects to have at least one element in array`)}var ue=t=>(e,n)=>{if(typeof n!==t)throw new Error(`"${e.name}" expects value to be a "${t}"`)},at={type:"compound",validate:it,parse(t,e,{parse:n}){let s=e.map(r=>n(r));return ae(t.name,s)}},Qt=at,Wt={type:"compound",validate:it},Xt={type:"field",validate(t,e){if(!(e&&(e instanceof RegExp||e.constructor===Object)))throw new Error(`"${t.name}" expects to receive either regular expression or object of field operators`)},parse(t,e,n){let s=e instanceof RegExp?new j("regex",n.field,e):n.parse(e,n);return new O(t.name,[s])}},le={type:"field",validate(t,e){if(!e||e.constructor!==Object)throw new Error(`"${t.name}" expects to receive an object with nested query or field level operators`)},parse(t,e,{parse:n,field:s,hasOperators:r}){let o=r(e)?n(e,{field:b}):n(e);return new j(t.name,s,o)}},fe={type:"field",validate:ue("number")},C={type:"field",validate:ot},pe=C,de=C,en={type:"field",validate(t,e){if(!Array.isArray(e)||e.length!==2)throw new Error(`"${t.name}" expects an array with 2 numeric elements`)}},he={type:"field",validate:ue("boolean")},z={type:"field",validate:function(t,e){if(!(typeof e=="string"||typeof e=="number"||e instanceof Date))throw new Error(`"${t.name}" expects value to be comparable (i.e., string, number or date)`)}},_=z,me=_,ye=_,B={type:"field"},be=B,ge={type:"field",validate(t,e){if(!(e instanceof RegExp)&&typeof e!="string")throw new Error(`"${t.name}" expects value to be a regular expression or a string that represents regular expression`)},parse(t,e,n){let s=typeof e=="string"?new RegExp(e,n.query.$options||""):e;return new j(t.name,n.field,s)}},xe={type:"field",parse:()=>ie},tn={type:"document",validate:ue("function")},nn=Object.freeze({__proto__:null,$and:at,$or:Qt,$nor:Wt,$not:Xt,$elemMatch:le,$size:fe,$in:C,$nin:pe,$all:de,$mod:en,$exists:he,$gte:z,$gt:_,$lt:me,$lte:ye,$eq:B,$ne:be,$regex:ge,$options:xe,$where:tn}),q=class extends S{constructor(e){super(e,{defaultOperatorName:"$eq",operatorToConditionName:n=>n.slice(1)})}parse(e,n){return n&&n.field?ce(this.parseFieldOperators(n.field,e)):super.parse(e)}},V=nn;function Oe(t,e,n){for(let s=0,r=t.length;s<r;s++)if(n(t[s],e)===0)return!0;return!1}function je(t,e){return Array.isArray(t)&&Number.isNaN(Number(e))}function ct(t,e,n){if(!je(t,e))return n(t,e);let s=[];for(let r=0;r<t.length;r++){let o=n(t[r],e);o!==void 0&&(s=s.concat(o))}return s}function v(t){return(e,n,s)=>{let r=s.get(n,e.field);return Array.isArray(r)?r.some(o=>t(e,o,s)):t(e,r,s)}}var sn=Object.hasOwn||Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty),rn=(t,e)=>t[e];function ut(t,e,n){let s=e.lastIndexOf(".");return s===-1?[t,e]:[n(t,e.slice(0,s)),e.slice(s+1)]}function on(t,e,n=rn){if(e===b)return t;if(!t)throw new Error(`Unable to get field "${e}" out of ${String(t)}.`);return(function(s,r,o){if(r.indexOf(".")===-1)return ct(s,r,o);let i=r.split("."),a=s;for(let u=0,l=i.length;u<l;u++)if(a=ct(a,i[u],o),!a||typeof a!="object")return u<l-1?void 0:a;return a})(t,e,n)}function ve(t,e){return t===e?0:t>e?1:-1}function we(t,e={}){return st(t,Object.assign({get:on,compare:ve},e))}var lt=(t,e,{interpret:n})=>t.value.some(s=>n(s,e)),an=(t,e,n)=>!lt(t,e,n),$e=(t,e,{interpret:n})=>t.value.every(s=>n(s,e)),cn=(t,e,{interpret:n})=>!n(t.value[0],e),G=(t,e,{compare:n,get:s})=>{let r=s(e,t.field);return Array.isArray(r)&&!Array.isArray(t.value)?Oe(r,t.value,n):n(r,t.value)===0},Ae=(t,e,n)=>!G(t,e,n),Ee=v((t,e,n)=>{let s=n.compare(e,t.value);return s===0||s===-1}),Ie=v((t,e,n)=>n.compare(e,t.value)===-1),Ne=v((t,e,n)=>n.compare(e,t.value)===1),Fe=v((t,e,n)=>{let s=n.compare(e,t.value);return s===0||s===1}),Me=(t,e,{get:n})=>{if(t.field===b)return e!==void 0;let[s,r]=ut(e,t.field,n),o=i=>i==null?!!i===t.value:sn(i,r)===t.value;return je(s,r)?s.some(o):o(s)},un=v((t,e)=>typeof e=="number"&&e%t.value[0]===t.value[1]),Se=(t,e,{get:n})=>{let[s,r]=ut(e,t.field,n),o=i=>{let a=n(i,r);return Array.isArray(a)&&a.length===t.value};return t.field!==b&&je(s,r)?s.some(o):o(s)},Ce=v((t,e)=>typeof e=="string"&&t.value.test(e)),R=v((t,e,{compare:n})=>Oe(t.value,e,n)),_e=(t,e,n)=>!R(t,e,n),Re=(t,e,{compare:n,get:s})=>{let r=s(e,t.field);return Array.isArray(r)&&t.value.every(o=>Oe(r,o,n))},Te=(t,e,{interpret:n,get:s})=>{let r=s(e,t.field);return Array.isArray(r)&&r.some(o=>n(t.value,o))},ln=(t,e)=>t.value.call(e),fn=Object.freeze({__proto__:null,or:lt,nor:an,and:$e,not:cn,eq:G,ne:Ae,lte:Ee,lt:Ie,gt:Ne,gte:Fe,exists:Me,mod:un,size:Se,regex:Ce,within:R,nin:_e,all:Re,elemMatch:Te,where:ln}),Y=Object.assign({},fn,{in:R}),Qn=we(Y);function ft(t){return t===null||typeof t!="object"?t:t instanceof Date?t.getTime():t&&typeof t.toJSON=="function"?t.toJSON():t}var pn=(t,e)=>ve(ft(t),ft(e));function J(t,e,n){let s=new q(t),r=we(e,Object.assign({compare:pn},n));if(n&&n.forPrimitives){let o={field:b},i=s.parse;s.setParse(a=>i(a,o))}return rt(s.parse,r)}var ns=J(V,Y),ss=J(["$and","$or"].reduce((t,e)=>(t[e]=Object.assign({},t[e],{type:"field"}),t),Object.assign({},V,{$nor:Object.assign({},V.$nor,{type:"field",parse:U.compound})})),Y,{forPrimitives:!0});var bt=Object.hasOwn||((t,e)=>Object.prototype.hasOwnProperty.call(t,e));function Pe(t){return Array.isArray(t)?t:[t]}var I="__caslSubjectType__";function gt(t,e){if(e){if(!bt(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}var H=t=>{let e=typeof t;return e==="string"||e==="function"},xt=t=>t.modelName||t.name;function dn(t){return typeof t=="string"?t:xt(t)}function Ot(t){return bt(t,I)?t[I]:xt(t.constructor)}var pt={function:t=>t.constructor,string:Ot};function dt(t,e,n){for(let s=n;s<e.length;s++)t.push(e[s])}function ht(t,e){if(!t||!t.length)return e||[];if(!e||!e.length)return t||[];let n=0,s=0,r=[];for(;n<t.length&&s<e.length;)t[n].priority<e[s].priority?(r.push(t[n]),n++):t[n].priority>e[s].priority?(r.push(e[s]),s++):(r.push(t[n]),n++,s++);return dt(r,t,n),dt(r,e,s),r}function Z(t,e,n){let s=t.get(e);return s||(s=n(),t.set(e,s)),s}var hn=t=>t;function mn(t,e){let n;for(let s=0;s<t.length;s++){let r=e(t[s]);n&&r&&n.push(t[s]),r||(n??(n=t.slice(0,s)))}return n||t}function yn(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')}var ke=class{constructor(e,n,s=0){yn(e,n),this.action=n.resolveAction(e.action),this.subject=e.subject,this.inverted=!!e.inverted,this.conditions=e.conditions,this.reason=e.reason,this.origin=e,this.fields=e.fields?Pe(e.fields):void 0,this.priority=s,this.t=n}i(){return this.conditions&&!this.o&&(this.o=this.t.conditionsMatcher(this.conditions)),this.o}get ast(){let e=this.i();return e?e.ast:void 0}matchesConditions(e){return this.conditions?!e||H(e)?!this.inverted:this.i()(e):!0}matchesField(e){return this.fields?e?(this.u||(this.u=this.t.fieldMatcher(this.fields)),this.u(e)):!this.inverted:!0}};function bn(t,e){let n={value:t,prev:e,next:null};return e&&(e.next=n),n}function gn(t){t.next&&(t.next.prev=t.prev),t.prev&&(t.prev.next=t.next),t.next=t.prev=null}var mt=()=>({rules:[],merged:!1}),yt=()=>new Map,De=class{constructor(e=[],n={}){this.h=!1,this.l=new Map,this.p={conditionsMatcher:n.conditionsMatcher,fieldMatcher:n.fieldMatcher,resolveAction:n.resolveAction||hn},this.$=n.anyAction||"manage",this.A=n.anySubjectType||"all",this.m=e,this.M=!!n.detectSubjectType,this.j=n.detectSubjectType||Ot,this.v(e)}get rules(){return this.m}detectSubjectType(e){return H(e)?e:e?this.j(e):this.A}update(e){let n={rules:e,ability:this,target:this};return this._("update",n),this.m=e,this.v(e),this._("updated",n),this}v(e){let n=new Map,s;for(let r=e.length-1;r>=0;r--){let o=e.length-r-1,i=new ke(e[r],this.p,o),a=Pe(i.action),u=Pe(i.subject||this.A);!this.h&&i.fields&&(this.h=!0);for(let l=0;l<u.length;l++){let h=Z(n,u[l],yt);s===void 0&&(s=typeof u[l]),typeof u[l]!==s&&s!=="mixed"&&(s="mixed");for(let A=0;A<a.length;A++)Z(h,a[A],mt).rules.push(i)}}if(this.l=n,s!=="mixed"&&!this.M){let r=pt[s]||pt.string;this.j=r}}possibleRulesFor(e,n=this.A){if(!H(n))throw new Error('"possibleRulesFor" accepts only subject types (i.e., string or class) as the 2nd parameter');let s=Z(this.l,n,yt),r=Z(s,e,mt);if(r.merged)return r.rules;let o=e!==this.$&&s.has(this.$)?s.get(this.$).rules:void 0,i=ht(r.rules,o);return n!==this.A&&(i=ht(i,this.possibleRulesFor(e,this.A))),r.rules=i,r.merged=!0,i}rulesFor(e,n,s){let r=this.possibleRulesFor(e,n);if(s&&typeof s!="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");return this.h?mn(r,o=>o.matchesField(s)):r}actionsFor(e){if(!H(e))throw new Error('"actionsFor" accepts only subject types (i.e., string or class) as a parameter');let n=new Set,s=this.l.get(e);s&&Array.from(s.keys()).forEach(o=>n.add(o));let r=e!==this.A?this.l.get(this.A):void 0;return r&&Array.from(r.keys()).forEach(o=>n.add(o)),Array.from(n)}on(e,n){this.F=this.F||new Map;let s=this.F,r=s.get(e)||null,o=bn(n,r);return s.set(e,o),()=>{let i=s.get(e);!o.next&&!o.prev&&i===o?s.delete(e):o===i&&s.set(e,o.prev),gn(o)}}_(e,n){if(!this.F)return;let s=this.F.get(e)||null,r=[];for(;s!==null;)r.push(s.value),s=s.prev;for(let o=0;o<r.length;o++)r[o](n)}},Le=class extends De{can(e,n,s){let r=this.relevantRuleFor(e,n,s);return!!r&&!r.inverted}relevantRuleFor(e,n,s){let r=this.detectSubjectType(n),o=this.rulesFor(e,r,s);for(let i=0,a=o.length;i<a;i++)if(o[i].matchesConditions(n))return o[i];return null}cannot(e,n,s){return!this.can(e,n,s)}},xn={$eq:B,$ne:be,$lt:me,$lte:ye,$gt:_,$gte:z,$in:C,$nin:pe,$all:de,$size:fe,$regex:ge,$options:xe,$elemMatch:le,$exists:he},On={eq:G,ne:Ae,lt:Ie,lte:Ee,gt:Ne,gte:Fe,in:R,nin:_e,all:Re,size:Se,regex:Ce,elemMatch:Te,exists:Me,and:$e};var jn=J(xn,On),vn=/[-/\\^$+?.()|[\]{}]/g,wn=/\.?\*+\.?/g,$n=/\*+/,An=/\./g;function En(t,e,n){let s=n[0]==="*"||t[0]==="."&&t[t.length-1]==="."?"+":"*",r=t.indexOf("**")===-1?"[^.]":".",o=t.replace(An,"\\$&").replace($n,r+s);return e+t.length===n.length?`(?:${o})?`:o}function In(t,e,n){return t==="."&&(n[e-1]==="*"||n[e+1]==="*")?t:`\\${t}`}function Nn(t){let e=t.map(s=>s.replace(vn,In).replace(wn,En)),n=e.length>1?`(?:${e.join("|")})`:e[0];return new RegExp(`^${n}$`)}var Fn=t=>{let e;return n=>(typeof e>"u"&&(e=t.every(s=>s.indexOf("*")===-1)?null:Nn(t)),e===null?t.indexOf(n)!==-1:e.test(n))};function jt(t=[],e={}){return new Le(t,Object.assign({conditionsMatcher:jn,fieldMatcher:Fn},e))}var Mn=t=>`Cannot execute "${t.action}" on "${t.subjectType}"`,vt=function(e){this.message=e};vt.prototype=Object.create(Error.prototype);var Ue=class extends vt{static setDefaultMessage(e){this.P=typeof e=="string"?()=>e:e}static from(e){return new this(e)}constructor(e){super(""),this.ability=e,typeof Error.captureStackTrace=="function"&&(this.name="ForbiddenError",Error.captureStackTrace(this,this.constructor))}setMessage(e){return this.message=e,this}throwUnlessCan(e,n,s){let r=this.unlessCan(e,n,s);if(r)throw r}unlessCan(e,n,s){let r=this.ability.relevantRuleFor(e,n,s);if(r&&!r.inverted)return;this.action=e,this.subject=n,this.subjectType=dn(this.ability.detectSubjectType(n)),this.field=s;let o=r?r.reason:"";return this.message=this.message||o||this.constructor.P(this),this}};Ue.P=Mn;var us=Object.freeze({__proto__:null});function qe(t,e,n){if(t==null)return t;if(typeof t=="string"){if(t.indexOf("$principal.")!==0)return t;let r=t.slice(11).split(".").reduce((o,i)=>o==null?o:o[i],e);return r==null&&(n.unresolved=!0),r}if(Array.isArray(t))return t.map(s=>qe(s,e,n));if(typeof t=="object"){let s={};for(let r of Object.keys(t))s[r]=qe(t[r],e,n);return s}return t}function K(t,e){let n={unresolved:!1};return{conditions:qe(t,e,n),unresolved:n.unresolved}}function wt(t,e){return K(t,e).conditions}function T(t,e){let n=D(t,e),s=[];for(let r of e.rules){if(n.indexOf(r.subject)===-1)continue;let o={action:r.actions,subject:r.resource};if(r.where){let{conditions:i,unresolved:a}=K(r.where,t);if(a)continue;o.conditions=i}s.push(o)}return s}function N(t){return jt(Array.isArray(t)?t:[])}function $t(t,e){return N(T(t,e))}function w(t,e,n,s){return s==null?t.can(e,n):t.can(e,gt(n,Object.assign({},s)))}var $={ALL:"all",NONE:"none",FIELDS:"fields",AMBIGUOUS:"ambiguous"},At={$in:"in",$nin:"nin",$ne:"ne",$gt:"gt",$gte:"gte",$lt:"lt",$lte:"lte"};function Sn(t){let e=[];for(let n of Object.keys(t)){let s=t[n];if(s===null||typeof s!="object"||Array.isArray(s)){e.push({field:n,op:"eq",value:s});continue}let r=Object.keys(s);if(r.length!==1||!At[r[0]])return null;e.push({field:n,op:At[r[0]],value:s[r[0]]})}return e}var Cn=(t,e)=>t==="manage"||t===e||Array.isArray(t)&&(t.indexOf(e)!==-1||t.indexOf("manage")!==-1),_n=(t,e)=>t==="all"||t===e;function Et(t,e,n,s){let r=T(t,e).filter(i=>Cn(i.action,n)&&_n(i.subject,s));if(r.length===0)return{scope:$.NONE,clauses:[]};if(r.some(i=>!i.conditions))return{scope:$.ALL,clauses:[]};if(r.length>1)return{scope:$.AMBIGUOUS,clauses:[]};let o=Sn(r[0].conditions);return o?{scope:$.FIELDS,clauses:o}:{scope:$.AMBIGUOUS,clauses:[]}}function It(t,e){let n=t;for(let s of e)s.op==="in"?n=n.hasSome(s.field,s.value):s.op==="nin"?n=n.not(n.hasSome(s.field,s.value)):n=n[s.op](s.field,s.value);return n}var ze=/export\s+const\s+([A-Za-z0-9_$]+)\s*=\s*webMethod\s*\(\s*Permissions\s*\.\s*([A-Za-z0-9_$]+)/g,Rn=[[/export\s*{\s*[A-Za-z0-9_$,\s]+}/,"export { x } \u2014 the call and the export must be one statement"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*Permissions\s*\[/,"Permissions['X'] \u2014 the property must be dotted and literal"],[/export\s+const\s+[A-Za-z0-9_$]+\s*=\s*webMethod\s*\(\s*[A-Za-z0-9_$]+\s*\(/,"a computed permission \u2014 it must be written out as Permissions.LEVEL"]];function Be(t){let e={},n=String(t||"");ze.lastIndex=0;let s=ze.exec(n);for(;s;)e[s[1]]=s[2],s=ze.exec(n);return e}function Ve(t,e,n){let s=n||{},r=e&&e.api||{},o=Be(t),i=String(t||""),a=[],u=[];for(let p of Object.keys(o)){let c=r[p];c?c.permission!==o[p]&&a.push({name:p,declared:c.permission,written:o[p]}):u.push({name:p,gate:o[p]})}let l=s.complete?Object.keys(r).filter(p=>!(p in o)):[],h=[];for(let[p,c]of Rn)p.test(i)&&h.push(c);return{ok:a.length+u.length+l.length+h.length===0,found:o,mismatched:a,undeclared:u,missing:l,suspect:h}}function Nt(t,e,n){let s=Ve(t,e,n);if(s.ok)return!0;let r=[];for(let o of s.mismatched)r.push(o.name+": policy says "+o.declared+", the export says "+o.written);for(let o of s.undeclared)r.push(o.name+": gated "+o.gate+" but missing from policy.api");for(let o of s.missing)r.push(o+": declared in policy.api but not exported here");for(let o of s.suspect)r.push("unreachable export shape \u2014 "+o);throw new Error(`wix-access: web-method gates do not match the policy:
2
+ `+r.join(`
3
+ `))}function Ft(t,e){let n=e&&e.api||{},s=t||{},r={},o=[];for(let i of Object.keys(s)){let a=s[i],u=n[i];if(!u){o.push(i);continue}if(typeof a!="function"){o.push(i+" (not a function: "+typeof a+")");continue}try{a.permission=u.permission,r[i]=u.permission}catch(l){o.push(i+" (could not stamp: "+String(l&&l.message)+")")}}if(o.length)throw new Error("wix-access: applyGates could not gate: "+o.join(", ")+". Every exported web method must be declared in policy.api.");return r}var Ge="0.5.0";var Ye=[{action:"read",type:"Booking",object:{customerId:"m-1"}},{action:"read",type:"Booking",object:{customerId:"m-2"}},{action:"cancel",type:"Booking",object:{customerId:"m-1"}},{action:"delete",type:"Booking",object:{customerId:"m-1"}},{action:"manage",type:"Vendor",object:{_id:"v-1"}}];function Mt(t){return Ye.map(e=>({action:e.action,type:e.type,object:e.object,can:w(t,e.action,e.type,e.object)}))}var Q=N([]),St="wix-access: createAccess({ fetchRules }) needs your web method, e.g. import { getMyAbilities } from 'backend/access.web'. The package cannot import it for you \u2014 that specifier only resolves inside your project. If it is imported and still not a function, build the kit inside onReady and pass an arrow: fetchRules: (...a) => getMyAbilities(...a).";function Ct(t){let e=t||{},n=e.fetchRules,s=e.onError||null,r=typeof n!="function",o=Q,i=[],a=!1,u=!1,l=null,h=null;async function A(){if(r)return i=[],o=Q,u=!0,l=St,a=!0,s&&s(new Error(St)),p;try{let c=await n();if(k(c))return i=[],o=Q,u=!0,l="rules refused: "+(c.code||"FORBIDDEN"),a=!0,s&&s(new Error(l)),p;i=Array.isArray(c)?c:[],o=N(i),u=!1}catch(c){i=[],o=Q,u=!0,l=String(c&&c.message||c),s&&s(c)}return a=!0,p}let p={ready(){return a?Promise.resolve(p):(h||(h=A().then(c=>(h=null,c))),h)},refresh(){return a=!1,u=!1,l=null,h=null,p.ready()},can:(c,d,g)=>w(o,c,d,g),cannot:(c,d,g)=>!w(o,c,d,g),rules:()=>i.slice(),get loaded(){return a},get failed(){return u},get reason(){return l},guard(c,d,g,P,W){let Je=p.can(d,g,P);return p.apply(c,Je,W),Je},apply(c,d,g){if(!c)return d;let P=g||"hide";try{P==="disable"?d&&c.enable?c.enable():!d&&c.disable&&c.disable():P==="collapse"?d&&c.expand?c.expand():!d&&c.collapse&&c.collapse():d&&c.show?c.show():!d&&c.hide&&c.hide()}catch(W){s&&s(W)}return d}};return p}function Tn(){return{ok:!0,side:"public",version:Ge}}async function Pn(){try{return(await _t.currentMember.getRoles()).map(e=>e.title)}catch{return[]}}0&&(module.exports={CASES,CODES,KIND,PACKAGE_VERSION,PolicyError,SCOPE,WHEN,abilityFor,abilityFromRules,anonymous,applyClauses,applyGates,assertGates,can,caseTable,createAccess,createPrincipal,deny,denyOpaque,filterFor,frontendRoleTitles,hasRole,isDenial,normaliseRoles,ok,parseGates,permissionFor,publicPing,resolvePlaceholders,resolveSubjects,resolveWhere,rulesFor,validatePolicy,verifyGates});
package/types.d.ts CHANGED
@@ -22,8 +22,13 @@ export interface Rule {
22
22
  export interface CollectionSpec {
23
23
  /** Resource name used in rules. Defaults to the collection id. */
24
24
  resource?: string
25
- /** Field the gateway stamps with the caller's member id — `_owner` is unusable. */
25
+ /**
26
+ * Field holding whose row this is — `_owner` is unusable. The gateway sets it to the
27
+ * caller's member id, or to `onBehalfOf`; never from the record. Moves only by `transfer`.
28
+ */
26
29
  owner?: string
30
+ /** Field stamped with the member id of whoever really created the row. Never changes. */
31
+ actor?: string
27
32
  tenant?: string
28
33
  profile?: string
29
34
  }