@nymphjs/tilmeld 1.0.0-alpha.4 → 1.0.0-alpha.42
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/CHANGELOG.md +186 -0
- package/dist/Group.js +13 -7
- package/dist/Group.js.map +1 -1
- package/dist/Group.test.js +6 -0
- package/dist/Group.test.js.map +1 -1
- package/dist/Tilmeld.js +115 -49
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +40 -2
- package/dist/User.js +130 -15
- package/dist/User.js.map +1 -1
- package/dist/User.test.js +6 -0
- package/dist/User.test.js.map +1 -1
- package/dist/conf/defaults.js +22 -101
- package/dist/conf/defaults.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/tilmeldJoiProps.d.ts +12 -0
- package/dist/tilmeldJoiProps.js +20 -0
- package/dist/tilmeldJoiProps.js.map +1 -0
- package/package.json +16 -16
- package/src/Group.test.ts +8 -0
- package/src/Group.ts +13 -7
- package/src/Tilmeld.ts +162 -57
- package/src/User.test.ts +8 -0
- package/src/User.ts +246 -19
- package/src/conf/d.ts +1 -0
- package/src/conf/defaults.ts +7 -57
- package/src/index.ts +3 -0
- package/src/tilmeldJoiProps.ts +46 -0
package/src/Group.ts
CHANGED
|
@@ -106,9 +106,9 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
106
106
|
'getPrimaryGroups',
|
|
107
107
|
'getSecondaryGroups',
|
|
108
108
|
];
|
|
109
|
-
protected $privateData = Group.DEFAULT_PRIVATE_DATA;
|
|
110
|
-
public static searchRestrictedData = Group.DEFAULT_PRIVATE_DATA;
|
|
111
|
-
protected $allowlistData? = Group.DEFAULT_ALLOWLIST_DATA;
|
|
109
|
+
protected $privateData = [...Group.DEFAULT_PRIVATE_DATA];
|
|
110
|
+
public static searchRestrictedData = [...Group.DEFAULT_PRIVATE_DATA];
|
|
111
|
+
protected $allowlistData? = [...Group.DEFAULT_ALLOWLIST_DATA];
|
|
112
112
|
protected $allowlistTags?: string[] = [];
|
|
113
113
|
|
|
114
114
|
/**
|
|
@@ -294,8 +294,8 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
294
294
|
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
295
295
|
let user = givenUser ?? tilmeld.User.current();
|
|
296
296
|
|
|
297
|
-
this.$privateData = Group.DEFAULT_PRIVATE_DATA;
|
|
298
|
-
this.$allowlistData = Group.DEFAULT_ALLOWLIST_DATA;
|
|
297
|
+
this.$privateData = [...Group.DEFAULT_PRIVATE_DATA];
|
|
298
|
+
this.$allowlistData = [...Group.DEFAULT_ALLOWLIST_DATA];
|
|
299
299
|
|
|
300
300
|
if (tilmeld.config.emailUsernames) {
|
|
301
301
|
this.$privateData.push('groupname');
|
|
@@ -746,13 +746,16 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
746
746
|
}
|
|
747
747
|
|
|
748
748
|
public async $delete() {
|
|
749
|
-
|
|
749
|
+
let tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
750
750
|
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
751
751
|
throw new BadDataError("You don't have the authority to delete groups.");
|
|
752
752
|
}
|
|
753
753
|
|
|
754
754
|
const transaction = 'tilmeld-delete-' + this.guid;
|
|
755
|
-
const
|
|
755
|
+
const nymph = this.$nymph;
|
|
756
|
+
const tnymph = await nymph.startTransaction(transaction);
|
|
757
|
+
this.$nymph = tnymph;
|
|
758
|
+
tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
756
759
|
|
|
757
760
|
// Delete descendants.
|
|
758
761
|
const descendants = await this.$getDescendants();
|
|
@@ -760,6 +763,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
760
763
|
for (let curGroup of descendants) {
|
|
761
764
|
if (!(await curGroup.$delete())) {
|
|
762
765
|
await tnymph.rollback(transaction);
|
|
766
|
+
this.$nymph = nymph;
|
|
763
767
|
return false;
|
|
764
768
|
}
|
|
765
769
|
}
|
|
@@ -780,6 +784,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
780
784
|
delete user.group;
|
|
781
785
|
if (!(await user.$save())) {
|
|
782
786
|
await tnymph.rollback(transaction);
|
|
787
|
+
this.$nymph = nymph;
|
|
783
788
|
return false;
|
|
784
789
|
}
|
|
785
790
|
}
|
|
@@ -810,6 +815,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
810
815
|
} else {
|
|
811
816
|
await tnymph.rollback(transaction);
|
|
812
817
|
}
|
|
818
|
+
this.$nymph = nymph;
|
|
813
819
|
return success;
|
|
814
820
|
}
|
|
815
821
|
}
|
package/src/Tilmeld.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
TilmeldAccessLevels,
|
|
8
8
|
} from '@nymphjs/nymph';
|
|
9
9
|
import { Request, Response } from 'express';
|
|
10
|
+
import { xor } from 'lodash';
|
|
10
11
|
|
|
11
12
|
import { Config, ConfigDefaults as defaults } from './conf';
|
|
12
13
|
import { AccessControlError } from './errors';
|
|
@@ -147,14 +148,13 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
private initAccessControl() {
|
|
150
|
-
const tilmeld = this;
|
|
151
|
-
|
|
152
151
|
// Check for the skip access control option and add AC selectors.
|
|
153
152
|
const handleQuery = function (
|
|
154
|
-
|
|
153
|
+
nymph: Nymph,
|
|
155
154
|
options: Options,
|
|
156
155
|
selectors: FormattedSelector[]
|
|
157
156
|
) {
|
|
157
|
+
const tilmeld = nymph.tilmeld as Tilmeld;
|
|
158
158
|
if (
|
|
159
159
|
!options ||
|
|
160
160
|
!('skipAc' in options) ||
|
|
@@ -191,9 +191,10 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
191
191
|
|
|
192
192
|
// Filter entities being deleted for user permissions.
|
|
193
193
|
const checkPermissionsDelete = function (
|
|
194
|
-
|
|
194
|
+
nymph: Nymph,
|
|
195
195
|
entity: EntityInterface
|
|
196
196
|
) {
|
|
197
|
+
const tilmeld = nymph.tilmeld as Tilmeld;
|
|
197
198
|
if (
|
|
198
199
|
typeof entity.$tilmeldDeleteSkipAC === 'function' &&
|
|
199
200
|
entity.$tilmeldDeleteSkipAC()
|
|
@@ -201,7 +202,7 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
201
202
|
return;
|
|
202
203
|
}
|
|
203
204
|
// Test for permissions.
|
|
204
|
-
if (tilmeld.checkPermissions(entity, TilmeldAccessLevels.FULL_ACCESS)) {
|
|
205
|
+
if (!tilmeld.checkPermissions(entity, TilmeldAccessLevels.FULL_ACCESS)) {
|
|
205
206
|
throw new AccessControlError('No permission to delete.');
|
|
206
207
|
}
|
|
207
208
|
};
|
|
@@ -213,8 +214,8 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
213
214
|
guid: string,
|
|
214
215
|
className?: string
|
|
215
216
|
) {
|
|
216
|
-
const entity =
|
|
217
|
-
{ class:
|
|
217
|
+
const entity = nymph.driver.getEntitySync(
|
|
218
|
+
{ class: nymph.getEntityClass(className ?? 'Entity') },
|
|
218
219
|
{ type: '&', guid: guid }
|
|
219
220
|
);
|
|
220
221
|
if (entity != null) {
|
|
@@ -226,9 +227,10 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
226
227
|
// Filter entities being saved for user permissions, and filter any
|
|
227
228
|
// disallowed changes to AC properties.
|
|
228
229
|
const checkPermissionsSaveAndFilterAcChanges = function (
|
|
229
|
-
|
|
230
|
+
nymph: Nymph,
|
|
230
231
|
entity: EntityInterface & AccessControlData
|
|
231
232
|
) {
|
|
233
|
+
const tilmeld = nymph.tilmeld as Tilmeld;
|
|
232
234
|
if (!entity) {
|
|
233
235
|
return;
|
|
234
236
|
}
|
|
@@ -244,15 +246,15 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
244
246
|
// allowing a change to ac properties.
|
|
245
247
|
|
|
246
248
|
const originalAc = entity.$getOriginalAcValues();
|
|
247
|
-
const newAc = {
|
|
248
|
-
user: entity.user ??
|
|
249
|
-
group: entity.group ??
|
|
250
|
-
acUser: entity.acUser ??
|
|
251
|
-
acGroup: entity.acGroup ??
|
|
252
|
-
acOther: entity.acOther ??
|
|
253
|
-
acRead: entity.acRead ??
|
|
254
|
-
acWrite: entity.acWrite ??
|
|
255
|
-
acFull: entity.acFull ??
|
|
249
|
+
const newAc: AccessControlData = {
|
|
250
|
+
user: entity.user ?? undefined,
|
|
251
|
+
group: entity.group ?? undefined,
|
|
252
|
+
acUser: entity.acUser ?? undefined,
|
|
253
|
+
acGroup: entity.acGroup ?? undefined,
|
|
254
|
+
acOther: entity.acOther ?? undefined,
|
|
255
|
+
acRead: entity.acRead ?? undefined,
|
|
256
|
+
acWrite: entity.acWrite ?? undefined,
|
|
257
|
+
acFull: entity.acFull ?? undefined,
|
|
256
258
|
};
|
|
257
259
|
|
|
258
260
|
const setAcProperties = (acValues: { [k: string]: any }) => {
|
|
@@ -268,10 +270,102 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
268
270
|
|
|
269
271
|
// Restore original AC properties and check permissions.
|
|
270
272
|
setAcProperties(originalAc);
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
273
|
+
|
|
274
|
+
function areAcPropertiesChanged(
|
|
275
|
+
a: AccessControlData,
|
|
276
|
+
b: AccessControlData
|
|
277
|
+
) {
|
|
278
|
+
for (const name of ['user', 'group'] as ('user' | 'group')[]) {
|
|
279
|
+
const aVal = a[name];
|
|
280
|
+
const bVal = b[name];
|
|
281
|
+
if (aVal == null && bVal == null) {
|
|
282
|
+
continue;
|
|
283
|
+
} else if (aVal == null || bVal == null) {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
if (!aVal.$is(bVal)) {
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
for (const name of ['acUser', 'acGroup', 'acOther'] as (
|
|
291
|
+
| 'acUser'
|
|
292
|
+
| 'acGroup'
|
|
293
|
+
| 'acOther'
|
|
294
|
+
)[]) {
|
|
295
|
+
const aVal = a[name];
|
|
296
|
+
const bVal = b[name];
|
|
297
|
+
if (aVal == null && bVal == null) {
|
|
298
|
+
continue;
|
|
299
|
+
} else if (aVal == null || bVal == null) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
if (aVal !== bVal) {
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
for (const name of ['acRead', 'acWrite', 'acFull'] as (
|
|
307
|
+
| 'acRead'
|
|
308
|
+
| 'acWrite'
|
|
309
|
+
| 'acFull'
|
|
310
|
+
)[]) {
|
|
311
|
+
const aVal = a[name];
|
|
312
|
+
const bVal = b[name];
|
|
313
|
+
if (aVal == null && bVal == null) {
|
|
314
|
+
continue;
|
|
315
|
+
} else if (aVal == null || bVal == null) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
if (aVal.length !== bVal.length) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
if (
|
|
322
|
+
xor(
|
|
323
|
+
aVal.map((entity) => entity.guid),
|
|
324
|
+
bVal.map((entity) => entity.guid)
|
|
325
|
+
).length
|
|
326
|
+
) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (areAcPropertiesChanged(originalAc, newAc)) {
|
|
334
|
+
if (
|
|
335
|
+
!tilmeld.checkPermissions(entity, TilmeldAccessLevels.FULL_ACCESS)
|
|
336
|
+
) {
|
|
337
|
+
// Only allow changes to AC properties if the user has full access.
|
|
338
|
+
throw new AccessControlError(
|
|
339
|
+
'No permission to change access control properties.'
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (
|
|
344
|
+
((originalAc.user && !originalAc.user.$is(newAc.user)) ||
|
|
345
|
+
(!originalAc.user &&
|
|
346
|
+
newAc.user &&
|
|
347
|
+
!newAc.user.$is(tilmeld.currentUser))) &&
|
|
348
|
+
!tilmeld.gatekeeper('tilmeld/admin')
|
|
349
|
+
) {
|
|
350
|
+
throw new AccessControlError(
|
|
351
|
+
'No permission to assign to another user.'
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (
|
|
356
|
+
newAc.group &&
|
|
357
|
+
!newAc.group.$is(originalAc.group) &&
|
|
358
|
+
!(
|
|
359
|
+
newAc.group.$is(tilmeld.currentUser?.group) ||
|
|
360
|
+
newAc.group.$inArray(tilmeld.currentUser?.groups ?? [])
|
|
361
|
+
) &&
|
|
362
|
+
!tilmeld.gatekeeper('tilmeld/admin')
|
|
363
|
+
) {
|
|
364
|
+
throw new AccessControlError(
|
|
365
|
+
'No permission to assign to another group.'
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
275
369
|
setAcProperties(newAc);
|
|
276
370
|
}
|
|
277
371
|
}
|
|
@@ -300,9 +394,10 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
300
394
|
* - acOther = TilmeldAccessLevels.NO_ACCESS
|
|
301
395
|
*/
|
|
302
396
|
const addAccess = function (
|
|
303
|
-
|
|
397
|
+
nymph: Nymph,
|
|
304
398
|
entity: EntityInterface & AccessControlData
|
|
305
399
|
) {
|
|
400
|
+
const tilmeld = nymph.tilmeld as Tilmeld;
|
|
306
401
|
const user = tilmeld.currentUser;
|
|
307
402
|
if (
|
|
308
403
|
user != null &&
|
|
@@ -353,30 +448,40 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
353
448
|
prop < TilmeldAccessLevels.NO_ACCESS ||
|
|
354
449
|
prop > TilmeldAccessLevels.FULL_ACCESS
|
|
355
450
|
) {
|
|
356
|
-
throw new AccessControlError(
|
|
451
|
+
throw new AccessControlError(
|
|
452
|
+
'Invalid access control property: ' + prop
|
|
453
|
+
);
|
|
357
454
|
}
|
|
358
455
|
};
|
|
359
456
|
|
|
360
457
|
const accessAcPropertyValidator = (prop: any) => {
|
|
361
458
|
if (!Array.isArray(prop)) {
|
|
362
|
-
throw new AccessControlError(
|
|
459
|
+
throw new AccessControlError(
|
|
460
|
+
'Invalid access control property: ' + prop
|
|
461
|
+
);
|
|
363
462
|
}
|
|
364
463
|
prop.forEach((value) => {
|
|
365
464
|
if (!(value instanceof User || value instanceof Group)) {
|
|
366
|
-
throw new AccessControlError(
|
|
465
|
+
throw new AccessControlError(
|
|
466
|
+
'Invalid access control property: ' + prop
|
|
467
|
+
);
|
|
367
468
|
}
|
|
368
469
|
});
|
|
369
470
|
};
|
|
370
471
|
|
|
371
472
|
if ('user' in entity) {
|
|
372
473
|
if (!(entity.user instanceof User)) {
|
|
373
|
-
throw new AccessControlError(
|
|
474
|
+
throw new AccessControlError(
|
|
475
|
+
'Invalid access control property: user'
|
|
476
|
+
);
|
|
374
477
|
}
|
|
375
478
|
}
|
|
376
479
|
|
|
377
480
|
if ('group' in entity) {
|
|
378
|
-
if (!(entity.
|
|
379
|
-
throw new AccessControlError(
|
|
481
|
+
if (!(entity.group instanceof Group)) {
|
|
482
|
+
throw new AccessControlError(
|
|
483
|
+
'Invalid access control property: group'
|
|
484
|
+
);
|
|
380
485
|
}
|
|
381
486
|
}
|
|
382
487
|
|
|
@@ -443,7 +548,7 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
443
548
|
return;
|
|
444
549
|
}
|
|
445
550
|
|
|
446
|
-
if (user
|
|
551
|
+
if (user == null || user.guid == null) {
|
|
447
552
|
selectors.push({
|
|
448
553
|
type: '|',
|
|
449
554
|
// Other access control is sufficient.
|
|
@@ -452,7 +557,7 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
452
557
|
selector: [
|
|
453
558
|
{
|
|
454
559
|
type: '&',
|
|
455
|
-
'!defined': ['user', 'group'],
|
|
560
|
+
'!defined': [['user', 'group']],
|
|
456
561
|
},
|
|
457
562
|
],
|
|
458
563
|
});
|
|
@@ -460,56 +565,43 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
460
565
|
const subSelectors: FormattedSelector[] = [
|
|
461
566
|
{
|
|
462
567
|
type: '&',
|
|
463
|
-
'!defined': ['user', 'group'],
|
|
568
|
+
'!defined': [['user', 'group']],
|
|
464
569
|
},
|
|
465
570
|
// It is owned by the user.
|
|
466
571
|
{
|
|
467
572
|
type: '&',
|
|
468
|
-
ref: [['user', user]],
|
|
573
|
+
ref: [['user', user.guid]],
|
|
469
574
|
gte: [['acUser', TilmeldAccessLevels.READ_ACCESS]],
|
|
470
575
|
},
|
|
471
576
|
];
|
|
472
|
-
const selector: FormattedSelector = {
|
|
473
|
-
type: '|',
|
|
474
|
-
// Other access control is sufficient.
|
|
475
|
-
gte: [['acOther', TilmeldAccessLevels.READ_ACCESS]],
|
|
476
|
-
// The user and group are not set.
|
|
477
|
-
selector: subSelectors,
|
|
478
|
-
// The user is listed in acRead, acWrite, or acFull.
|
|
479
|
-
ref: [
|
|
480
|
-
['acRead', user],
|
|
481
|
-
['acWrite', user],
|
|
482
|
-
['acFull', user],
|
|
483
|
-
],
|
|
484
|
-
};
|
|
485
577
|
const groupRefs: FormattedSelector['ref'] = [];
|
|
486
578
|
const acRefs: FormattedSelector['ref'] = [];
|
|
487
579
|
if (user.group != null && user.group.guid != null) {
|
|
488
580
|
// It belongs to the user's primary group.
|
|
489
|
-
groupRefs.push(['group', user.group]);
|
|
581
|
+
groupRefs.push(['group', user.group.guid]);
|
|
490
582
|
// User's primary group is listed in acRead, acWrite, or acFull.
|
|
491
|
-
acRefs.push(['acRead', user.group]);
|
|
492
|
-
acRefs.push(['acWrite', user.group]);
|
|
493
|
-
acRefs.push(['acFull', user.group]);
|
|
583
|
+
acRefs.push(['acRead', user.group.guid]);
|
|
584
|
+
acRefs.push(['acWrite', user.group.guid]);
|
|
585
|
+
acRefs.push(['acFull', user.group.guid]);
|
|
494
586
|
}
|
|
495
587
|
for (let curSecondaryGroup of user.groups ?? []) {
|
|
496
588
|
if (curSecondaryGroup != null && curSecondaryGroup.guid != null) {
|
|
497
589
|
// It belongs to the user's secondary group.
|
|
498
|
-
groupRefs.push(['group', curSecondaryGroup]);
|
|
590
|
+
groupRefs.push(['group', curSecondaryGroup.guid]);
|
|
499
591
|
// User's secondary group is listed in acRead, acWrite, or acFull.
|
|
500
|
-
acRefs.push(['acRead', curSecondaryGroup]);
|
|
501
|
-
acRefs.push(['acWrite', curSecondaryGroup]);
|
|
502
|
-
acRefs.push(['acFull', curSecondaryGroup]);
|
|
592
|
+
acRefs.push(['acRead', curSecondaryGroup.guid]);
|
|
593
|
+
acRefs.push(['acWrite', curSecondaryGroup.guid]);
|
|
594
|
+
acRefs.push(['acFull', curSecondaryGroup.guid]);
|
|
503
595
|
}
|
|
504
596
|
}
|
|
505
597
|
for (let curDescendantGroup of user.$getDescendantGroupsSync()) {
|
|
506
598
|
if (curDescendantGroup != null && curDescendantGroup.guid != null) {
|
|
507
599
|
// It belongs to the user's secondary group.
|
|
508
|
-
groupRefs.push(['group', curDescendantGroup]);
|
|
600
|
+
groupRefs.push(['group', curDescendantGroup.guid]);
|
|
509
601
|
// User's secondary group is listed in acRead, acWrite, or acFull.
|
|
510
|
-
acRefs.push(['acRead', curDescendantGroup]);
|
|
511
|
-
acRefs.push(['acWrite', curDescendantGroup]);
|
|
512
|
-
acRefs.push(['acFull', curDescendantGroup]);
|
|
602
|
+
acRefs.push(['acRead', curDescendantGroup.guid]);
|
|
603
|
+
acRefs.push(['acWrite', curDescendantGroup.guid]);
|
|
604
|
+
acRefs.push(['acFull', curDescendantGroup.guid]);
|
|
513
605
|
}
|
|
514
606
|
}
|
|
515
607
|
// All the group refs.
|
|
@@ -532,6 +624,19 @@ export default class Tilmeld implements TilmeldInterface {
|
|
|
532
624
|
ref: acRefs,
|
|
533
625
|
});
|
|
534
626
|
}
|
|
627
|
+
const selector: FormattedSelector = {
|
|
628
|
+
type: '|',
|
|
629
|
+
// Other access control is sufficient.
|
|
630
|
+
gte: [['acOther', TilmeldAccessLevels.READ_ACCESS]],
|
|
631
|
+
// The user and group are not set.
|
|
632
|
+
selector: subSelectors,
|
|
633
|
+
// The user is listed in acRead, acWrite, or acFull.
|
|
634
|
+
ref: [
|
|
635
|
+
['acRead', user.guid],
|
|
636
|
+
['acWrite', user.guid],
|
|
637
|
+
['acFull', user.guid],
|
|
638
|
+
],
|
|
639
|
+
};
|
|
535
640
|
selectors.push(selector);
|
|
536
641
|
}
|
|
537
642
|
}
|
package/src/User.test.ts
CHANGED
|
@@ -40,6 +40,14 @@ describe('User', () => {
|
|
|
40
40
|
return newUser;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
it('new user passes validation', async () => {
|
|
44
|
+
const validUser = await makeNewUser();
|
|
45
|
+
|
|
46
|
+
expect(() => {
|
|
47
|
+
defaults.validatorUser(validUser);
|
|
48
|
+
}).not.toThrow();
|
|
49
|
+
});
|
|
50
|
+
|
|
43
51
|
it("doesn't allow unknown keys", async () => {
|
|
44
52
|
const invalidUser = await makeNewUser();
|
|
45
53
|
|