@webiny/api-headless-cms 5.39.1 → 5.39.2-beta.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.
Files changed (50) hide show
  1. package/context.js +14 -26
  2. package/context.js.map +1 -1
  3. package/crud/AccessControl/AccessControl.d.ts +98 -0
  4. package/crud/AccessControl/AccessControl.js +542 -0
  5. package/crud/AccessControl/AccessControl.js.map +1 -0
  6. package/crud/AccessControl/README.md +47 -0
  7. package/crud/AccessControl/groups-own.png +0 -0
  8. package/crud/AccessControl/models-own.png +0 -0
  9. package/crud/contentEntry/entryDataFactories/createEntryData.d.ts +3 -3
  10. package/crud/contentEntry/entryDataFactories/createEntryData.js +21 -3
  11. package/crud/contentEntry/entryDataFactories/createEntryData.js.map +1 -1
  12. package/crud/contentEntry/entryDataFactories/createEntryRevisionFromData.d.ts +3 -1
  13. package/crud/contentEntry/entryDataFactories/createEntryRevisionFromData.js +54 -11
  14. package/crud/contentEntry/entryDataFactories/createEntryRevisionFromData.js.map +1 -1
  15. package/crud/contentEntry.crud.d.ts +2 -4
  16. package/crud/contentEntry.crud.js +106 -113
  17. package/crud/contentEntry.crud.js.map +1 -1
  18. package/crud/contentModel.crud.d.ts +2 -2
  19. package/crud/contentModel.crud.js +45 -31
  20. package/crud/contentModel.crud.js.map +1 -1
  21. package/crud/contentModelGroup.crud.d.ts +2 -2
  22. package/crud/contentModelGroup.crud.js +17 -28
  23. package/crud/contentModelGroup.crud.js.map +1 -1
  24. package/index.d.ts +2 -1
  25. package/index.js +24 -12
  26. package/index.js.map +1 -1
  27. package/package.json +19 -19
  28. package/plugins/CmsModelPlugin.d.ts +1 -1
  29. package/plugins/CmsModelPlugin.js +4 -3
  30. package/plugins/CmsModelPlugin.js.map +1 -1
  31. package/types.d.ts +12 -10
  32. package/types.js.map +1 -1
  33. package/utils/createModelField.d.ts +5 -0
  34. package/utils/createModelField.js +41 -0
  35. package/utils/createModelField.js.map +1 -0
  36. package/utils/isHeadlessCmsReady.d.ts +2 -0
  37. package/utils/isHeadlessCmsReady.js +23 -0
  38. package/utils/isHeadlessCmsReady.js.map +1 -0
  39. package/utils/access.d.ts +0 -9
  40. package/utils/access.js +0 -26
  41. package/utils/access.js.map +0 -1
  42. package/utils/permissions/EntriesPermissions.d.ts +0 -4
  43. package/utils/permissions/EntriesPermissions.js +0 -11
  44. package/utils/permissions/EntriesPermissions.js.map +0 -1
  45. package/utils/permissions/ModelGroupsPermissions.d.ts +0 -9
  46. package/utils/permissions/ModelGroupsPermissions.js +0 -50
  47. package/utils/permissions/ModelGroupsPermissions.js.map +0 -1
  48. package/utils/permissions/ModelsPermissions.d.ts +0 -22
  49. package/utils/permissions/ModelsPermissions.js +0 -90
  50. package/utils/permissions/ModelsPermissions.js.map +0 -1
@@ -0,0 +1,542 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.AccessControl = void 0;
7
+ var _apiSecurity = require("@webiny/api-security");
8
+ class AccessControl {
9
+ constructor({
10
+ getIdentity,
11
+ getGroupsPermissions,
12
+ getModelsPermissions,
13
+ getEntriesPermissions,
14
+ listAllGroups
15
+ }) {
16
+ this.getIdentity = getIdentity;
17
+ this.getGroupsPermissions = getGroupsPermissions;
18
+ this.getModelsPermissions = getModelsPermissions;
19
+ this.getEntriesPermissions = getEntriesPermissions;
20
+ this.fullAccessPermissions = ["*", "cms.*"];
21
+ this.listAllGroupsCallback = listAllGroups;
22
+ this.allGroups = null;
23
+ }
24
+
25
+ /**
26
+ * Groups-related methods below. 👇
27
+ * - canAccessGroup
28
+ * - ensureCanAccessGroup
29
+ * - canAccessNonOwnedGroups
30
+ * - canAccessOnlyOwnedGroups
31
+ * - getGroupsAccessControlList
32
+ * - hasFullAccessToGroups
33
+ */
34
+
35
+ async canAccessGroup(params = {}) {
36
+ const acl = await this.getGroupsAccessControlList(params);
37
+ const canRead = acl.find(ace => ace.rwd?.includes("r"));
38
+ if (!canRead) {
39
+ return false;
40
+ }
41
+ const {
42
+ rwd
43
+ } = params;
44
+ if (rwd) {
45
+ const hasRwd = acl.find(ace => ace.rwd.includes(rwd));
46
+ if (!hasRwd) {
47
+ return false;
48
+ }
49
+ }
50
+ return true;
51
+ }
52
+ async ensureCanAccessGroup(params = {}) {
53
+ const canAccess = await this.canAccessGroup(params);
54
+ if (canAccess) {
55
+ return;
56
+ }
57
+ if ("group" in params) {
58
+ let groupName = "(could not determine name)";
59
+ if (params.group?.name) {
60
+ groupName = `"${params.group.name}"`;
61
+ }
62
+ throw new _apiSecurity.NotAuthorizedError({
63
+ data: {
64
+ reason: `Not allowed to access content model group ${groupName}.`
65
+ }
66
+ });
67
+ }
68
+ throw new _apiSecurity.NotAuthorizedError({
69
+ data: {
70
+ reason: `Not allowed to access content model groups.`
71
+ }
72
+ });
73
+ }
74
+ async canAccessNonOwnedGroups(params) {
75
+ const acl = await this.getGroupsAccessControlList(params);
76
+ return acl.some(ace => ace.canAccessNonOwned);
77
+ }
78
+ async canAccessOnlyOwnedGroups(params) {
79
+ const canAccessNonOwned = await this.canAccessNonOwnedGroups(params);
80
+ return !canAccessNonOwned;
81
+ }
82
+ async getGroupsAccessControlList(params) {
83
+ if (await this.hasFullAccessToGroups()) {
84
+ return [{
85
+ rwd: "rwd",
86
+ canAccessNonOwned: true,
87
+ canAccessOnlyOwned: false
88
+ }];
89
+ }
90
+ const groupsPermissionsList = await this.getGroupsPermissions();
91
+ const acl = [];
92
+ for (const groupsPermissions of groupsPermissionsList) {
93
+ if (groupsPermissions.own) {
94
+ if ("group" in params) {
95
+ const modelGroupCreatedBy = params.group?.createdBy;
96
+ if (!modelGroupCreatedBy) {
97
+ continue;
98
+ }
99
+ const identity = await this.getIdentity();
100
+ if (modelGroupCreatedBy.id !== identity.id) {
101
+ continue;
102
+ }
103
+ }
104
+ acl.push({
105
+ rwd: "rwd",
106
+ canAccessNonOwned: false,
107
+ canAccessOnlyOwned: true
108
+ });
109
+ }
110
+ if (groupsPermissions.groups) {
111
+ if ("group" in params) {
112
+ const {
113
+ group
114
+ } = params;
115
+ if (!group) {
116
+ continue;
117
+ }
118
+ const {
119
+ groups
120
+ } = groupsPermissions;
121
+ if (!Array.isArray(groups[group.locale])) {
122
+ continue;
123
+ }
124
+ if (!groups[group.locale].includes(group.id)) {
125
+ continue;
126
+ }
127
+ }
128
+ }
129
+ acl.push({
130
+ rwd: groupsPermissions.rwd,
131
+ canAccessNonOwned: true,
132
+ canAccessOnlyOwned: false
133
+ });
134
+ }
135
+ return acl;
136
+ }
137
+ async hasFullAccessToGroups() {
138
+ const permissions = await this.getGroupsPermissions();
139
+ return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));
140
+ }
141
+
142
+ /**
143
+ * Models-related methods below. 👇
144
+ * - canAccessModel
145
+ * - ensureCanAccessModel
146
+ * - canAccessNonOwnedModels
147
+ * - canAccessOnlyOwnedModels
148
+ * - getModelsAccessControlList
149
+ * - hasFullAccessToModels
150
+ */
151
+
152
+ async canAccessModel(params) {
153
+ const acl = await this.getModelsAccessControlList(params);
154
+ const canRead = acl.find(ace => ace.rwd.includes("r"));
155
+ if (!canRead) {
156
+ return false;
157
+ }
158
+ const {
159
+ rwd
160
+ } = params;
161
+ if (rwd) {
162
+ const hasRwd = acl.find(ace => ace.rwd.includes(rwd));
163
+ if (!hasRwd) {
164
+ return false;
165
+ }
166
+ }
167
+ return true;
168
+ }
169
+ async ensureCanAccessModel(params = {}) {
170
+ const canAccess = await this.canAccessModel(params);
171
+ if (canAccess) {
172
+ return;
173
+ }
174
+ if ("model" in params) {
175
+ let modelName = "(could not determine name)";
176
+ if (params.model?.name) {
177
+ modelName = `"${params.model.name}"`;
178
+ }
179
+ throw new _apiSecurity.NotAuthorizedError({
180
+ data: {
181
+ reason: `Not allowed to access content model ${modelName}.`
182
+ }
183
+ });
184
+ }
185
+ throw new _apiSecurity.NotAuthorizedError({
186
+ data: {
187
+ reason: `Not allowed to access content models.`
188
+ }
189
+ });
190
+ }
191
+ async canAccessNonOwnedModels(params) {
192
+ const acl = await this.getModelsAccessControlList(params);
193
+ return acl.some(ace => ace.canAccessNonOwned);
194
+ }
195
+ async canAccessOnlyOwnedModels(params) {
196
+ const canAccessNonOwned = await this.canAccessNonOwnedModels(params);
197
+ return !canAccessNonOwned;
198
+ }
199
+ async getModelsAccessControlList(params) {
200
+ if (await this.hasFullAccessToModels(params)) {
201
+ return [{
202
+ rwd: "rwd",
203
+ canAccessNonOwned: true,
204
+ canAccessOnlyOwned: false
205
+ }];
206
+ }
207
+ const groupsPermissionsList = await this.getGroupsPermissions();
208
+ const acl = [];
209
+ for (let i = 0; i < groupsPermissionsList.length; i++) {
210
+ const groupsPermissions = groupsPermissionsList[i];
211
+ const modelsPermissionsList = await this.getModelsPermissions();
212
+ const relatedModelPermissions = modelsPermissionsList.find(permissions => permissions._src === groupsPermissions._src);
213
+ if (!relatedModelPermissions) {
214
+ continue;
215
+ }
216
+ if (groupsPermissions.own) {
217
+ if ("model" in params) {
218
+ const {
219
+ model
220
+ } = params;
221
+ if (!model) {
222
+ continue;
223
+ }
224
+ const group = await this.getGroup(model.group.id);
225
+ if (!group) {
226
+ continue;
227
+ }
228
+ const modelGroupCreatedBy = group.createdBy;
229
+ if (!modelGroupCreatedBy) {
230
+ continue;
231
+ }
232
+ const identity = await this.getIdentity();
233
+ if (modelGroupCreatedBy.id !== identity.id) {
234
+ continue;
235
+ }
236
+ }
237
+ acl.push({
238
+ rwd: "rwd",
239
+ canAccessNonOwned: false,
240
+ canAccessOnlyOwned: true
241
+ });
242
+ continue;
243
+ }
244
+ if (groupsPermissions.groups) {
245
+ if ("model" in params) {
246
+ const {
247
+ model
248
+ } = params;
249
+ if (!model) {
250
+ continue;
251
+ }
252
+ if (!Array.isArray(groupsPermissions.groups[model.locale])) {
253
+ continue;
254
+ }
255
+ if (!groupsPermissions.groups[model.locale].includes(model.group.id)) {
256
+ continue;
257
+ }
258
+ }
259
+ }
260
+ const fullAccess = !relatedModelPermissions.rwd && !relatedModelPermissions.own && !relatedModelPermissions.models;
261
+ if (fullAccess) {
262
+ acl.push({
263
+ rwd: "rwd",
264
+ canAccessNonOwned: true,
265
+ canAccessOnlyOwned: false
266
+ });
267
+ continue;
268
+ }
269
+ if (relatedModelPermissions.own) {
270
+ if ("model" in params) {
271
+ if (!params.model) {
272
+ continue;
273
+ }
274
+ const modelCreatedBy = params.model.createdBy;
275
+ if (!modelCreatedBy) {
276
+ continue;
277
+ }
278
+ const identity = await this.getIdentity();
279
+ if (modelCreatedBy.id !== identity.id) {
280
+ continue;
281
+ }
282
+ }
283
+ acl.push({
284
+ rwd: "rwd",
285
+ canAccessNonOwned: false,
286
+ canAccessOnlyOwned: true
287
+ });
288
+ continue;
289
+ }
290
+ if (relatedModelPermissions.models) {
291
+ const {
292
+ models
293
+ } = relatedModelPermissions;
294
+ if ("model" in params) {
295
+ if (!params.model) {
296
+ continue;
297
+ }
298
+ if (!Array.isArray(models[params.model.locale])) {
299
+ continue;
300
+ }
301
+ if (!models[params.model.locale].includes(params.model.modelId)) {
302
+ continue;
303
+ }
304
+ }
305
+ }
306
+ acl.push({
307
+ rwd: relatedModelPermissions.rwd,
308
+ canAccessNonOwned: true,
309
+ canAccessOnlyOwned: false
310
+ });
311
+ }
312
+ return acl;
313
+ }
314
+ async hasFullAccessToModels(params) {
315
+ const {
316
+ model
317
+ } = params;
318
+ if (model) {
319
+ if (this.modelAuthorizationDisabled({
320
+ model
321
+ })) {
322
+ return true;
323
+ }
324
+ }
325
+ const permissions = await this.getModelsPermissions();
326
+ return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));
327
+ }
328
+
329
+ /**
330
+ * Entries-related methods below. 👇
331
+ * - canAccessEntry
332
+ * - ensureCanAccessEntry
333
+ * - canAccessNonOwnedEntries
334
+ * - canAccessOnlyOwnedEntries
335
+ * - getEntriesAccessControlList
336
+ * - hasFullAccessToEntries
337
+ */
338
+
339
+ async canAccessEntry(params) {
340
+ const acl = await this.getEntriesAccessControlList(params);
341
+ const canRead = acl.find(ace => ace.rwd.includes("r"));
342
+ if (!canRead) {
343
+ return false;
344
+ }
345
+ const {
346
+ rwd
347
+ } = params;
348
+ if (rwd) {
349
+ const hasRwd = acl.find(ace => ace.rwd.includes(rwd));
350
+ if (!hasRwd) {
351
+ return false;
352
+ }
353
+ }
354
+ const {
355
+ pw
356
+ } = params;
357
+ if (pw) {
358
+ const hasPw = acl.find(ace => ace.pw?.includes(pw));
359
+ if (!hasPw) {
360
+ return false;
361
+ }
362
+ }
363
+ return true;
364
+ }
365
+ async ensureCanAccessEntry(params) {
366
+ const canAccess = await this.canAccessEntry(params);
367
+ if (!canAccess) {
368
+ if (params.entry) {
369
+ throw new _apiSecurity.NotAuthorizedError({
370
+ data: {
371
+ reason: `Not allowed to access entry "${params.entry.entryId}".`
372
+ }
373
+ });
374
+ }
375
+ throw new _apiSecurity.NotAuthorizedError({
376
+ data: {
377
+ reason: `Not allowed to access "${params.model.modelId}" entries.`
378
+ }
379
+ });
380
+ }
381
+ }
382
+ async canAccessNonOwnedEntries(params) {
383
+ const acl = await this.getEntriesAccessControlList(params);
384
+ return acl.some(ace => ace.canAccessNonOwned);
385
+ }
386
+ async canAccessOnlyOwnedEntries(params) {
387
+ const canAccessNonOwned = await this.canAccessNonOwnedEntries(params);
388
+ return !canAccessNonOwned;
389
+ }
390
+ async getEntriesAccessControlList(params) {
391
+ if (await this.hasFullAccessToEntries(params)) {
392
+ return [{
393
+ rwd: "rwd",
394
+ pw: "pu",
395
+ canAccessNonOwned: true,
396
+ canAccessOnlyOwned: false
397
+ }];
398
+ }
399
+ const {
400
+ model
401
+ } = params;
402
+ const groupsPermissionsList = await this.getGroupsPermissions();
403
+ const acl = [];
404
+ for (let i = 0; i < groupsPermissionsList.length; i++) {
405
+ const groupPermissions = groupsPermissionsList[i];
406
+ const modelsPermissionsList = await this.getModelsPermissions();
407
+ const relatedModelsPermissions = modelsPermissionsList.find(permissions => permissions._src === groupPermissions._src);
408
+ if (!relatedModelsPermissions) {
409
+ continue;
410
+ }
411
+ const entriesPermissionsList = await this.getEntriesPermissions();
412
+ const relatedEntriesPermissions = entriesPermissionsList.find(permissions => permissions._src === groupPermissions._src);
413
+ if (!relatedEntriesPermissions) {
414
+ continue;
415
+ }
416
+ if (groupPermissions.own) {
417
+ const group = await this.getGroup(model.group.id);
418
+ if (!group) {
419
+ continue;
420
+ }
421
+ const groupCreatedBy = group.createdBy;
422
+ if (!groupCreatedBy) {
423
+ continue;
424
+ }
425
+ const identity = await this.getIdentity();
426
+ if (groupCreatedBy.id !== identity.id) {
427
+ continue;
428
+ }
429
+ acl.push({
430
+ rwd: "rwd",
431
+ canAccessNonOwned: false,
432
+ canAccessOnlyOwned: true,
433
+ pw: relatedEntriesPermissions.pw
434
+ });
435
+ continue;
436
+ }
437
+ if (groupPermissions.groups) {
438
+ const {
439
+ groups
440
+ } = groupPermissions;
441
+ if (!Array.isArray(groups[model.locale])) {
442
+ continue;
443
+ }
444
+ if (!groups[model.locale].includes(model.group.id)) {
445
+ continue;
446
+ }
447
+ }
448
+ if (relatedModelsPermissions.own) {
449
+ const modelCreatedBy = model.createdBy;
450
+ if (!modelCreatedBy) {
451
+ continue;
452
+ }
453
+ const identity = await this.getIdentity();
454
+ if (modelCreatedBy.id !== identity.id) {
455
+ continue;
456
+ }
457
+ acl.push({
458
+ rwd: "rwd",
459
+ canAccessNonOwned: false,
460
+ canAccessOnlyOwned: true,
461
+ pw: relatedEntriesPermissions.pw
462
+ });
463
+ }
464
+ if (relatedModelsPermissions.models) {
465
+ if (!Array.isArray(relatedModelsPermissions.models[model.locale])) {
466
+ continue;
467
+ }
468
+ if (!relatedModelsPermissions.models[model.locale].includes(model.modelId)) {
469
+ continue;
470
+ }
471
+ }
472
+ const fullAccess = !relatedEntriesPermissions.rwd && !relatedEntriesPermissions.own && !relatedEntriesPermissions.models;
473
+ if (fullAccess) {
474
+ acl.push({
475
+ rwd: "rwd",
476
+ canAccessNonOwned: false,
477
+ canAccessOnlyOwned: true,
478
+ pw: "pu"
479
+ });
480
+ continue;
481
+ }
482
+ if (relatedEntriesPermissions.own) {
483
+ if ("entry" in params) {
484
+ const entryCreatedBy = params.entry?.createdBy;
485
+ if (!entryCreatedBy) {
486
+ continue;
487
+ }
488
+ const identity = await this.getIdentity();
489
+ if (entryCreatedBy.id !== identity.id) {
490
+ continue;
491
+ }
492
+ }
493
+ acl.push({
494
+ rwd: relatedEntriesPermissions.rwd,
495
+ canAccessNonOwned: false,
496
+ canAccessOnlyOwned: true,
497
+ pw: relatedEntriesPermissions.pw
498
+ });
499
+ continue;
500
+ }
501
+ acl.push({
502
+ rwd: relatedEntriesPermissions.rwd,
503
+ canAccessNonOwned: true,
504
+ canAccessOnlyOwned: false,
505
+ pw: relatedEntriesPermissions.pw
506
+ });
507
+ }
508
+ return acl;
509
+ }
510
+ async hasFullAccessToEntries(params) {
511
+ if (this.modelAuthorizationDisabled(params)) {
512
+ return true;
513
+ }
514
+ const permissions = await this.getEntriesPermissions();
515
+ return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));
516
+ }
517
+ modelAuthorizationDisabled(params) {
518
+ if ("authorization" in params.model) {
519
+ const {
520
+ authorization
521
+ } = params.model;
522
+ if (typeof authorization === "boolean") {
523
+ return authorization === false;
524
+ }
525
+ return authorization?.permissions === false;
526
+ }
527
+ return false;
528
+ }
529
+ async listAllGroups() {
530
+ if (this.allGroups === null) {
531
+ this.allGroups = this.listAllGroupsCallback();
532
+ }
533
+ return this.allGroups;
534
+ }
535
+ async getGroup(id) {
536
+ const groups = await this.listAllGroups();
537
+ return groups.find(group => group.id === id);
538
+ }
539
+ }
540
+ exports.AccessControl = AccessControl;
541
+
542
+ //# sourceMappingURL=AccessControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_apiSecurity","require","AccessControl","constructor","getIdentity","getGroupsPermissions","getModelsPermissions","getEntriesPermissions","listAllGroups","fullAccessPermissions","listAllGroupsCallback","allGroups","canAccessGroup","params","acl","getGroupsAccessControlList","canRead","find","ace","rwd","includes","hasRwd","ensureCanAccessGroup","canAccess","groupName","group","name","NotAuthorizedError","data","reason","canAccessNonOwnedGroups","some","canAccessNonOwned","canAccessOnlyOwnedGroups","hasFullAccessToGroups","canAccessOnlyOwned","groupsPermissionsList","groupsPermissions","own","modelGroupCreatedBy","createdBy","identity","id","push","groups","Array","isArray","locale","permissions","p","filter","Boolean","canAccessModel","getModelsAccessControlList","ensureCanAccessModel","modelName","model","canAccessNonOwnedModels","canAccessOnlyOwnedModels","hasFullAccessToModels","i","length","modelsPermissionsList","relatedModelPermissions","_src","getGroup","fullAccess","models","modelCreatedBy","modelId","modelAuthorizationDisabled","canAccessEntry","getEntriesAccessControlList","pw","hasPw","ensureCanAccessEntry","entry","entryId","canAccessNonOwnedEntries","canAccessOnlyOwnedEntries","hasFullAccessToEntries","groupPermissions","relatedModelsPermissions","entriesPermissionsList","relatedEntriesPermissions","groupCreatedBy","entryCreatedBy","authorization","exports"],"sources":["AccessControl.ts"],"sourcesContent":["import { NotAuthorizedError } from \"@webiny/api-security\";\nimport { SecurityIdentity } from \"@webiny/api-security/types\";\nimport {\n CmsEntry,\n CmsEntryPermission,\n CmsGroup,\n CmsGroupPermission,\n CmsModel,\n CmsModelPermission\n} from \"~/types\";\n\nexport interface AccessControlParams {\n getIdentity: () => SecurityIdentity | Promise<SecurityIdentity>;\n getGroupsPermissions: () => CmsGroupPermission[] | Promise<CmsGroupPermission[]>;\n getModelsPermissions: () => CmsModelPermission[] | Promise<CmsModelPermission[]>;\n getEntriesPermissions: () => CmsEntryPermission[] | Promise<CmsEntryPermission[]>;\n listAllGroups: () => Promise<CmsGroup[]>;\n}\n\ninterface GetGroupsAccessControlListParams {\n group?: CmsGroup;\n}\n\ninterface CanAccessGroupParams extends GetGroupsAccessControlListParams {\n rwd?: string;\n}\n\ninterface GetModelsAccessControlListParams {\n model?: CmsModel;\n}\n\ninterface CanAccessModelParams extends GetModelsAccessControlListParams {\n rwd?: string;\n}\n\ninterface GetEntriesAccessControlListParams {\n model: CmsModel;\n entry?: CmsEntry;\n}\n\ninterface CanAccessEntryParams extends GetEntriesAccessControlListParams {\n rwd?: string;\n pw?: string;\n}\n\ninterface AccessControlEntry {\n rwd: string;\n canAccessNonOwned: boolean;\n canAccessOnlyOwned: boolean;\n}\n\ntype AccessControlList = AccessControlEntry[];\n\ninterface EntriesAccessControlEntry extends AccessControlEntry {\n pw?: string;\n}\n\ntype EntriesAccessControlList = EntriesAccessControlEntry[];\n\nexport class AccessControl {\n getIdentity: AccessControlParams[\"getIdentity\"];\n getGroupsPermissions: AccessControlParams[\"getGroupsPermissions\"];\n getModelsPermissions: AccessControlParams[\"getModelsPermissions\"];\n getEntriesPermissions: AccessControlParams[\"getEntriesPermissions\"];\n listAllGroupsCallback: AccessControlParams[\"listAllGroups\"];\n\n private fullAccessPermissions: string[];\n private allGroups: null | CmsGroup[] | Promise<CmsGroup[]>;\n\n constructor({\n getIdentity,\n getGroupsPermissions,\n getModelsPermissions,\n getEntriesPermissions,\n listAllGroups\n }: AccessControlParams) {\n this.getIdentity = getIdentity;\n this.getGroupsPermissions = getGroupsPermissions;\n this.getModelsPermissions = getModelsPermissions;\n this.getEntriesPermissions = getEntriesPermissions;\n this.fullAccessPermissions = [\"*\", \"cms.*\"];\n this.listAllGroupsCallback = listAllGroups;\n this.allGroups = null;\n }\n\n /**\n * Groups-related methods below. 👇\n * - canAccessGroup\n * - ensureCanAccessGroup\n * - canAccessNonOwnedGroups\n * - canAccessOnlyOwnedGroups\n * - getGroupsAccessControlList\n * - hasFullAccessToGroups\n */\n\n async canAccessGroup(params: CanAccessGroupParams = {}) {\n const acl = await this.getGroupsAccessControlList(params);\n\n const canRead = acl.find(ace => ace.rwd?.includes(\"r\"));\n if (!canRead) {\n return false;\n }\n\n const { rwd } = params;\n if (rwd) {\n const hasRwd = acl.find(ace => ace.rwd.includes(rwd));\n if (!hasRwd) {\n return false;\n }\n }\n\n return true;\n }\n\n async ensureCanAccessGroup(params: CanAccessGroupParams = {}) {\n const canAccess = await this.canAccessGroup(params);\n if (canAccess) {\n return;\n }\n\n if (\"group\" in params) {\n let groupName = \"(could not determine name)\";\n if (params.group?.name) {\n groupName = `\"${params.group.name}\"`;\n }\n\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access content model group ${groupName}.`\n }\n });\n }\n\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access content model groups.`\n }\n });\n }\n\n async canAccessNonOwnedGroups(params: GetGroupsAccessControlListParams) {\n const acl = await this.getGroupsAccessControlList(params);\n return acl.some(ace => ace.canAccessNonOwned);\n }\n\n async canAccessOnlyOwnedGroups(params: GetGroupsAccessControlListParams) {\n const canAccessNonOwned = await this.canAccessNonOwnedGroups(params);\n return !canAccessNonOwned;\n }\n\n async getGroupsAccessControlList(\n params: GetGroupsAccessControlListParams\n ): Promise<AccessControlList> {\n if (await this.hasFullAccessToGroups()) {\n return [{ rwd: \"rwd\", canAccessNonOwned: true, canAccessOnlyOwned: false }];\n }\n\n const groupsPermissionsList = await this.getGroupsPermissions();\n const acl: AccessControlList = [];\n\n for (const groupsPermissions of groupsPermissionsList) {\n if (groupsPermissions.own) {\n if (\"group\" in params) {\n const modelGroupCreatedBy = params.group?.createdBy;\n if (!modelGroupCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n\n if (modelGroupCreatedBy.id !== identity.id) {\n continue;\n }\n }\n\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true\n });\n }\n\n if (groupsPermissions.groups) {\n if (\"group\" in params) {\n const { group } = params;\n if (!group) {\n continue;\n }\n\n const { groups } = groupsPermissions;\n if (!Array.isArray(groups[group.locale])) {\n continue;\n }\n\n if (!groups[group.locale].includes(group.id)) {\n continue;\n }\n }\n }\n\n acl.push({\n rwd: groupsPermissions.rwd as string,\n canAccessNonOwned: true,\n canAccessOnlyOwned: false\n });\n }\n\n return acl;\n }\n\n async hasFullAccessToGroups() {\n const permissions = await this.getGroupsPermissions();\n return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));\n }\n\n /**\n * Models-related methods below. 👇\n * - canAccessModel\n * - ensureCanAccessModel\n * - canAccessNonOwnedModels\n * - canAccessOnlyOwnedModels\n * - getModelsAccessControlList\n * - hasFullAccessToModels\n */\n\n async canAccessModel(params: CanAccessModelParams) {\n const acl = await this.getModelsAccessControlList(params);\n\n const canRead = acl.find(ace => ace.rwd.includes(\"r\"));\n if (!canRead) {\n return false;\n }\n\n const { rwd } = params;\n if (rwd) {\n const hasRwd = acl.find(ace => ace.rwd.includes(rwd));\n if (!hasRwd) {\n return false;\n }\n }\n\n return true;\n }\n\n async ensureCanAccessModel(params: CanAccessModelParams = {}) {\n const canAccess = await this.canAccessModel(params);\n if (canAccess) {\n return;\n }\n\n if (\"model\" in params) {\n let modelName = \"(could not determine name)\";\n if (params.model?.name) {\n modelName = `\"${params.model.name}\"`;\n }\n\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access content model ${modelName}.`\n }\n });\n }\n\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access content models.`\n }\n });\n }\n\n async canAccessNonOwnedModels(params: GetModelsAccessControlListParams) {\n const acl = await this.getModelsAccessControlList(params);\n return acl.some(ace => ace.canAccessNonOwned);\n }\n\n async canAccessOnlyOwnedModels(params: GetModelsAccessControlListParams) {\n const canAccessNonOwned = await this.canAccessNonOwnedModels(params);\n return !canAccessNonOwned;\n }\n\n async getModelsAccessControlList(\n params: GetModelsAccessControlListParams\n ): Promise<AccessControlList> {\n if (await this.hasFullAccessToModels(params)) {\n return [{ rwd: \"rwd\", canAccessNonOwned: true, canAccessOnlyOwned: false }];\n }\n\n const groupsPermissionsList = await this.getGroupsPermissions();\n const acl: AccessControlList = [];\n\n for (let i = 0; i < groupsPermissionsList.length; i++) {\n const groupsPermissions = groupsPermissionsList[i];\n\n const modelsPermissionsList = await this.getModelsPermissions();\n const relatedModelPermissions = modelsPermissionsList.find(\n permissions => permissions._src === groupsPermissions._src\n );\n\n if (!relatedModelPermissions) {\n continue;\n }\n\n if (groupsPermissions.own) {\n if (\"model\" in params) {\n const { model } = params;\n if (!model) {\n continue;\n }\n\n const group = await this.getGroup(model.group.id);\n if (!group) {\n continue;\n }\n\n const modelGroupCreatedBy = group.createdBy;\n if (!modelGroupCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n if (modelGroupCreatedBy.id !== identity.id) {\n continue;\n }\n }\n\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true\n });\n\n continue;\n }\n\n if (groupsPermissions.groups) {\n if (\"model\" in params) {\n const { model } = params;\n if (!model) {\n continue;\n }\n\n if (!Array.isArray(groupsPermissions.groups[model.locale])) {\n continue;\n }\n\n if (!groupsPermissions.groups[model.locale].includes(model.group.id)) {\n continue;\n }\n }\n }\n\n const fullAccess =\n !relatedModelPermissions.rwd &&\n !relatedModelPermissions.own &&\n !relatedModelPermissions.models;\n\n if (fullAccess) {\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: true,\n canAccessOnlyOwned: false\n });\n\n continue;\n }\n\n if (relatedModelPermissions.own) {\n if (\"model\" in params) {\n if (!params.model) {\n continue;\n }\n\n const modelCreatedBy = params.model.createdBy;\n if (!modelCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n if (modelCreatedBy.id !== identity.id) {\n continue;\n }\n }\n\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true\n });\n\n continue;\n }\n\n if (relatedModelPermissions.models) {\n const { models } = relatedModelPermissions;\n if (\"model\" in params) {\n if (!params.model) {\n continue;\n }\n\n if (!Array.isArray(models[params.model.locale])) {\n continue;\n }\n\n if (!models[params.model.locale].includes(params.model.modelId)) {\n continue;\n }\n }\n }\n\n acl.push({\n rwd: relatedModelPermissions.rwd as string,\n canAccessNonOwned: true,\n canAccessOnlyOwned: false\n });\n }\n\n return acl;\n }\n\n async hasFullAccessToModels(params: GetModelsAccessControlListParams) {\n const { model } = params;\n if (model) {\n if (this.modelAuthorizationDisabled({ model })) {\n return true;\n }\n }\n\n const permissions = await this.getModelsPermissions();\n return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));\n }\n\n /**\n * Entries-related methods below. 👇\n * - canAccessEntry\n * - ensureCanAccessEntry\n * - canAccessNonOwnedEntries\n * - canAccessOnlyOwnedEntries\n * - getEntriesAccessControlList\n * - hasFullAccessToEntries\n */\n\n async canAccessEntry(params: CanAccessEntryParams) {\n const acl = await this.getEntriesAccessControlList(params);\n\n const canRead = acl.find(ace => ace.rwd.includes(\"r\"));\n if (!canRead) {\n return false;\n }\n\n const { rwd } = params;\n if (rwd) {\n const hasRwd = acl.find(ace => ace.rwd.includes(rwd));\n if (!hasRwd) {\n return false;\n }\n }\n\n const { pw } = params;\n if (pw) {\n const hasPw = acl.find(ace => ace.pw?.includes(pw));\n if (!hasPw) {\n return false;\n }\n }\n\n return true;\n }\n\n async ensureCanAccessEntry(params: CanAccessEntryParams) {\n const canAccess = await this.canAccessEntry(params);\n if (!canAccess) {\n if (params.entry) {\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access entry \"${params.entry.entryId}\".`\n }\n });\n }\n\n throw new NotAuthorizedError({\n data: {\n reason: `Not allowed to access \"${params.model.modelId}\" entries.`\n }\n });\n }\n }\n\n async canAccessNonOwnedEntries(params: GetEntriesAccessControlListParams) {\n const acl = await this.getEntriesAccessControlList(params);\n return acl.some(ace => ace.canAccessNonOwned);\n }\n\n async canAccessOnlyOwnedEntries(params: GetEntriesAccessControlListParams) {\n const canAccessNonOwned = await this.canAccessNonOwnedEntries(params);\n return !canAccessNonOwned;\n }\n\n async getEntriesAccessControlList(\n params: GetEntriesAccessControlListParams\n ): Promise<EntriesAccessControlList> {\n if (await this.hasFullAccessToEntries(params)) {\n return [{ rwd: \"rwd\", pw: \"pu\", canAccessNonOwned: true, canAccessOnlyOwned: false }];\n }\n\n const { model } = params;\n const groupsPermissionsList = await this.getGroupsPermissions();\n const acl: EntriesAccessControlList = [];\n\n for (let i = 0; i < groupsPermissionsList.length; i++) {\n const groupPermissions = groupsPermissionsList[i];\n\n const modelsPermissionsList = await this.getModelsPermissions();\n const relatedModelsPermissions = modelsPermissionsList.find(\n permissions => permissions._src === groupPermissions._src\n );\n\n if (!relatedModelsPermissions) {\n continue;\n }\n\n const entriesPermissionsList = await this.getEntriesPermissions();\n const relatedEntriesPermissions = entriesPermissionsList.find(\n permissions => permissions._src === groupPermissions._src\n );\n\n if (!relatedEntriesPermissions) {\n continue;\n }\n\n if (groupPermissions.own) {\n const group = await this.getGroup(model.group.id);\n if (!group) {\n continue;\n }\n\n const groupCreatedBy = group.createdBy;\n if (!groupCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n if (groupCreatedBy.id !== identity.id) {\n continue;\n }\n\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true,\n pw: relatedEntriesPermissions.pw\n });\n\n continue;\n }\n\n if (groupPermissions.groups) {\n const { groups } = groupPermissions;\n\n if (!Array.isArray(groups[model.locale])) {\n continue;\n }\n\n if (!groups[model.locale].includes(model.group.id)) {\n continue;\n }\n }\n\n if (relatedModelsPermissions.own) {\n const modelCreatedBy = model.createdBy;\n if (!modelCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n if (modelCreatedBy.id !== identity.id) {\n continue;\n }\n\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true,\n pw: relatedEntriesPermissions.pw\n });\n }\n\n if (relatedModelsPermissions.models) {\n if (!Array.isArray(relatedModelsPermissions.models[model.locale])) {\n continue;\n }\n\n if (!relatedModelsPermissions.models[model.locale].includes(model.modelId)) {\n continue;\n }\n }\n\n const fullAccess =\n !relatedEntriesPermissions.rwd &&\n !relatedEntriesPermissions.own &&\n !relatedEntriesPermissions.models;\n\n if (fullAccess) {\n acl.push({\n rwd: \"rwd\",\n canAccessNonOwned: false,\n canAccessOnlyOwned: true,\n pw: \"pu\"\n });\n\n continue;\n }\n\n if (relatedEntriesPermissions.own) {\n if (\"entry\" in params) {\n const entryCreatedBy = params.entry?.createdBy;\n if (!entryCreatedBy) {\n continue;\n }\n\n const identity = await this.getIdentity();\n if (entryCreatedBy.id !== identity.id) {\n continue;\n }\n }\n\n acl.push({\n rwd: relatedEntriesPermissions.rwd,\n canAccessNonOwned: false,\n canAccessOnlyOwned: true,\n pw: relatedEntriesPermissions.pw\n });\n\n continue;\n }\n\n acl.push({\n rwd: relatedEntriesPermissions.rwd,\n canAccessNonOwned: true,\n canAccessOnlyOwned: false,\n pw: relatedEntriesPermissions.pw\n });\n }\n\n return acl;\n }\n\n async hasFullAccessToEntries(params: GetEntriesAccessControlListParams) {\n if (this.modelAuthorizationDisabled(params)) {\n return true;\n }\n\n const permissions = await this.getEntriesPermissions();\n return permissions.some(p => this.fullAccessPermissions.filter(Boolean).includes(p.name));\n }\n\n private modelAuthorizationDisabled(params: { model: CmsModel }) {\n if (\"authorization\" in params.model) {\n const { authorization } = params.model;\n if (typeof authorization === \"boolean\") {\n return authorization === false;\n }\n\n return authorization?.permissions === false;\n }\n\n return false;\n }\n\n async listAllGroups(): Promise<CmsGroup[]> {\n if (this.allGroups === null) {\n this.allGroups = this.listAllGroupsCallback();\n }\n\n return this.allGroups;\n }\n\n async getGroup(id: string): Promise<CmsGroup | undefined> {\n const groups = await this.listAllGroups();\n return groups.find(group => group.id === id);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ # How Access Control Works
2
+
3
+ With Headless CMS, checking base permissions (access control) is a bit more interesting because the three types of permissions objects are related to each other. The three types of permissions are:
4
+
5
+ 1. `cms.contentModelGroup`
6
+ 2. `cms.contentModel`
7
+ 3. `cms.contentEntry`
8
+
9
+ So, for example, when checking if a user can create content entries, it's not enough to check if the user has the `cms.contentEntry` permission. We also need to check if the user has the `cms.contentModel` permission for the content model the entry belongs to, and if the user has the `cms.contentModelGroup` permission for the content model group the content model belongs to.
10
+
11
+ All of the above is handled by the `AccessControl` class, which provides a set of methods to check if a user has the necessary permissions to perform a specific action. The main methods that are used in CRUD operations-related code are:
12
+
13
+ 1. `canAccessGroup` (`ensureCanAccessGroup`): checks if a user has the necessary permissions to access a content model group.
14
+ 2. `canAccessModel` (`ensureCanAccessModel`): checks if a user has the necessary permissions to access a content model (takes into consideration the content model group permissions).
15
+ 3. `canAccessEntry` (`ensureCanAccessEntry`): checks if a user has the necessary permissions to access a content entry (takes into consideration the content model and content model group permissions).
16
+
17
+ Note that all of these methods can accept an exact entity instance if needed, but it's not required. Both has its own use cases.
18
+
19
+ For example, when checking if a user can access (read) a content entry, you can pass the entry instance to the `canAccessEntry` method, and it will check if the user has the necessary permissions to access that specific entry. On the other hand, if the entry instance was not passed, the method would check if the user has the necessary permissions to access (read) entries of the given content model.
20
+
21
+ Note that, whenever possible, the entry should be passed to the method, as it's more secure and provides more accurate results. For example, it is possible to receive a `true` response when checking if a user can access a specific content model, but still receive `false` when the model was not passed (when checking if user can access / read models in general).
22
+
23
+ ## Folder Level Permissions
24
+
25
+ With Folder Level Permissions, a user can be part of a team, that may have multiple roles that provide different Headless CMS-related permissions (more information [here](https://www.webiny.com/docs/enterprise/aacl/teams#overview)).
26
+
27
+ The Access Control class is aware of this and ensures that only permissions objects from a single role are taken into consideration when checking if a user has the necessary permissions to perform a specific action. If permission objects from a single role do not provide the necessary permissions, the next role is checked, and so on.
28
+
29
+ In order to achieve this, we're using the `_src` property that's assigned to each permission object. This property contains the role ID, and is used to filter out permissions objects that belong to a different role.
30
+
31
+ ## Interesting Permissions-related Logic
32
+
33
+ ### Only groups created by the user
34
+
35
+ When choosing "Only groups created by the user" access scope via the `cms.contentModelGroup` permission, the user that possesses this permission can not only fully (r/w/d) access content models that belong to the content model groups that the user has created, but also content entries that belong to those content models.
36
+
37
+ <img src="./groups-own.png">
38
+
39
+ Note that only the entry publishing actions-related permissions are not automatically set here. They need to be defined when defining the role explicitly.
40
+
41
+ ### Only models created by the user
42
+
43
+ When choosing "Only models created by the user" access scope via the `cms.contentModel` permission, the user that possesses this permission can not only fully (r/w/d) access content models that the user has created, but also content entries that belong to those content models.
44
+
45
+ <img src="./models-own.png">
46
+
47
+ Note that only the entry publishing actions-related permissions are not automatically set here. They need to be defined when defining the role explicitly.