@nymphjs/tilmeld 1.0.0-beta.131 → 1.0.0-beta.133
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 +12 -0
- package/dist/AbleObject.d.ts +6 -3
- package/dist/AbleObject.js +9 -9
- package/dist/AbleObject.js.map +1 -1
- package/dist/Group.d.ts +24 -23
- package/dist/Group.js +84 -92
- package/dist/Group.js.map +1 -1
- package/dist/Tilmeld.d.ts +9 -9
- package/dist/Tilmeld.js +16 -8
- package/dist/Tilmeld.js.map +1 -1
- package/dist/Tilmeld.types.d.ts +6 -6
- package/dist/User.d.ts +32 -31
- package/dist/User.js +280 -289
- package/dist/User.js.map +1 -1
- package/dist/conf/defaults.js +2 -2
- package/dist/conf/defaults.js.map +1 -1
- package/dist/conf/index.d.ts +8 -10
- package/dist/conf/index.js.map +1 -1
- package/dist/index.d.ts +2 -8
- package/dist/index.js +2 -8
- package/dist/index.js.map +1 -1
- package/dist/testArtifacts.d.ts +4 -2
- package/dist/testArtifacts.js.map +1 -1
- package/dist/tilmeldJoiProps.d.ts +1 -2
- package/dist/tilmeldJoiProps.js +3 -3
- package/dist/tilmeldJoiProps.js.map +1 -1
- package/package.json +5 -5
- package/src/AbleObject.ts +17 -11
- package/src/Group.ts +98 -122
- package/src/Tilmeld.ts +25 -20
- package/src/Tilmeld.types.ts +6 -6
- package/src/User.ts +303 -348
- package/src/conf/defaults.ts +2 -2
- package/src/conf/index.ts +8 -14
- package/src/index.ts +2 -8
- package/src/testArtifacts.ts +6 -4
- package/src/tilmeldJoiProps.ts +3 -3
package/src/Group.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import {
|
|
3
|
-
type EntityData,
|
|
4
3
|
type EntityJson,
|
|
5
4
|
type EntityPatch,
|
|
6
5
|
type Options,
|
|
@@ -14,7 +13,7 @@ import { difference, xor } from 'lodash-es';
|
|
|
14
13
|
import { splitn } from '@sciactive/splitn';
|
|
15
14
|
|
|
16
15
|
import { enforceTilmeld } from './enforceTilmeld.js';
|
|
17
|
-
import AbleObject from './AbleObject.js';
|
|
16
|
+
import { AbleObject } from './AbleObject.js';
|
|
18
17
|
import {
|
|
19
18
|
AccessControlError,
|
|
20
19
|
BadDataError,
|
|
@@ -22,8 +21,7 @@ import {
|
|
|
22
21
|
BadUsernameError,
|
|
23
22
|
CouldNotChangeDefaultPrimaryGroupError,
|
|
24
23
|
} from './errors/index.js';
|
|
25
|
-
import UserClass from './User.js';
|
|
26
|
-
import type { UserData } from './User.js';
|
|
24
|
+
import { User as UserClass } from './User.js';
|
|
27
25
|
|
|
28
26
|
export type GroupEventType =
|
|
29
27
|
| 'checkGroupname'
|
|
@@ -37,7 +35,7 @@ export type GroupEventType =
|
|
|
37
35
|
* process and return the included message, disallowing the groupname.
|
|
38
36
|
*/
|
|
39
37
|
export type TilmeldCheckGroupnameCallback = (
|
|
40
|
-
group: Group
|
|
38
|
+
group: Group,
|
|
41
39
|
data: { groupname: string },
|
|
42
40
|
) => Promise<{ result: boolean; message?: string }>;
|
|
43
41
|
/**
|
|
@@ -45,33 +43,25 @@ export type TilmeldCheckGroupnameCallback = (
|
|
|
45
43
|
*
|
|
46
44
|
* The transaction is available in `group.$nymph`.
|
|
47
45
|
*/
|
|
48
|
-
export type TilmeldBeforeGroupSaveCallback = (
|
|
49
|
-
group: Group & GroupData,
|
|
50
|
-
) => Promise<void>;
|
|
46
|
+
export type TilmeldBeforeGroupSaveCallback = (group: Group) => Promise<void>;
|
|
51
47
|
/**
|
|
52
48
|
* This is run before the transaction is committed, and you can perform
|
|
53
49
|
* additional functions on the transaction, which is available in
|
|
54
50
|
* `group.$nymph`.
|
|
55
51
|
*/
|
|
56
|
-
export type TilmeldAfterGroupSaveCallback = (
|
|
57
|
-
group: Group & GroupData,
|
|
58
|
-
) => Promise<void>;
|
|
52
|
+
export type TilmeldAfterGroupSaveCallback = (group: Group) => Promise<void>;
|
|
59
53
|
/**
|
|
60
54
|
* The transaction is available in `group.$nymph`.
|
|
61
55
|
*/
|
|
62
|
-
export type TilmeldBeforeGroupDeleteCallback = (
|
|
63
|
-
group: Group & GroupData,
|
|
64
|
-
) => Promise<void>;
|
|
56
|
+
export type TilmeldBeforeGroupDeleteCallback = (group: Group) => Promise<void>;
|
|
65
57
|
/**
|
|
66
58
|
* This is run before the transaction is committed, and you can perform
|
|
67
59
|
* additional functions on the transaction, which is available in
|
|
68
60
|
* `group.$nymph`.
|
|
69
61
|
*/
|
|
70
|
-
export type TilmeldAfterGroupDeleteCallback = (
|
|
71
|
-
group: Group & GroupData,
|
|
72
|
-
) => Promise<void>;
|
|
62
|
+
export type TilmeldAfterGroupDeleteCallback = (group: Group) => Promise<void>;
|
|
73
63
|
|
|
74
|
-
export
|
|
64
|
+
export interface GroupData {
|
|
75
65
|
/**
|
|
76
66
|
* The abilities granted to the group.
|
|
77
67
|
*/
|
|
@@ -99,11 +89,11 @@ export type GroupData = {
|
|
|
99
89
|
/**
|
|
100
90
|
* The group's parent.
|
|
101
91
|
*/
|
|
102
|
-
parent?: Group
|
|
92
|
+
parent?: Group;
|
|
103
93
|
/**
|
|
104
94
|
* If generatePrimary is on, this will be the user who generated this group.
|
|
105
95
|
*/
|
|
106
|
-
user?:
|
|
96
|
+
user?: UserClass | null;
|
|
107
97
|
|
|
108
98
|
/**
|
|
109
99
|
* Whether the group can be used.
|
|
@@ -121,7 +111,9 @@ export type GroupData = {
|
|
|
121
111
|
* Whether this group is a default secondary group for unverified users.
|
|
122
112
|
*/
|
|
123
113
|
unverifiedSecondary?: boolean;
|
|
124
|
-
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface Group extends GroupData {}
|
|
125
117
|
|
|
126
118
|
/**
|
|
127
119
|
* A user group data model.
|
|
@@ -132,7 +124,7 @@ export type GroupData = {
|
|
|
132
124
|
* @copyright SciActive Inc
|
|
133
125
|
* @see http://nymph.io/
|
|
134
126
|
*/
|
|
135
|
-
export
|
|
127
|
+
export class Group extends AbleObject<GroupData> {
|
|
136
128
|
static ETYPE = 'tilmeld_group';
|
|
137
129
|
static class = 'Group';
|
|
138
130
|
private static checkGroupnameCallbacks: TilmeldCheckGroupnameCallback[] = [];
|
|
@@ -193,9 +185,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
193
185
|
return super.getFTSText(name, value);
|
|
194
186
|
}
|
|
195
187
|
|
|
196
|
-
static async factoryGroupname(
|
|
197
|
-
groupname?: string,
|
|
198
|
-
): Promise<Group & GroupData> {
|
|
188
|
+
static async factoryGroupname(groupname?: string): Promise<Group> {
|
|
199
189
|
const entity = new this();
|
|
200
190
|
if (groupname != null) {
|
|
201
191
|
const entity = await this.nymph.getEntity(
|
|
@@ -266,7 +256,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
266
256
|
selectors: Selector[],
|
|
267
257
|
) {
|
|
268
258
|
const tilmeld = enforceTilmeld(this);
|
|
269
|
-
let assignableGroups:
|
|
259
|
+
let assignableGroups: Group[] = [];
|
|
270
260
|
|
|
271
261
|
if (highestParent === false) {
|
|
272
262
|
return assignableGroups;
|
|
@@ -294,7 +284,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
294
284
|
return null;
|
|
295
285
|
}),
|
|
296
286
|
)
|
|
297
|
-
).filter((group) => group != null) as
|
|
287
|
+
).filter((group) => group != null) as Group[];
|
|
298
288
|
}
|
|
299
289
|
return assignableGroups;
|
|
300
290
|
}
|
|
@@ -303,38 +293,38 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
303
293
|
super();
|
|
304
294
|
|
|
305
295
|
// Defaults.
|
|
306
|
-
this
|
|
307
|
-
this
|
|
296
|
+
this.enabled = true;
|
|
297
|
+
this.abilities = [];
|
|
308
298
|
this.$updateDataProtection();
|
|
309
299
|
}
|
|
310
300
|
|
|
311
301
|
async $getUniques(): Promise<string[]> {
|
|
312
302
|
const tilmeld = enforceTilmeld(this);
|
|
313
|
-
const uniques = [`u:${this
|
|
303
|
+
const uniques = [`u:${this.groupname}`];
|
|
314
304
|
if (
|
|
315
305
|
!tilmeld.config.emailUsernames &&
|
|
316
306
|
tilmeld.config.userFields.includes('email')
|
|
317
307
|
) {
|
|
318
|
-
uniques.push(`e:${this
|
|
308
|
+
uniques.push(`e:${this.email}`);
|
|
319
309
|
}
|
|
320
|
-
if (this
|
|
310
|
+
if (this.defaultPrimary) {
|
|
321
311
|
uniques.push(`o:default-primary`);
|
|
322
312
|
}
|
|
323
313
|
return uniques;
|
|
324
314
|
}
|
|
325
315
|
|
|
326
316
|
public $getAvatar(): string {
|
|
327
|
-
if (this
|
|
328
|
-
return this
|
|
317
|
+
if (this.avatar != null && this.avatar !== '') {
|
|
318
|
+
return this.avatar;
|
|
329
319
|
}
|
|
330
|
-
if (this
|
|
320
|
+
if (this.email == null || !this.email.length) {
|
|
331
321
|
return 'https://secure.gravatar.com/avatar/?d=mm&s=40';
|
|
332
322
|
}
|
|
333
323
|
return (
|
|
334
324
|
'https://secure.gravatar.com/avatar/' +
|
|
335
325
|
crypto
|
|
336
326
|
.createHash('sha256')
|
|
337
|
-
.update(this
|
|
327
|
+
.update(this.email.trim().toLowerCase())
|
|
338
328
|
.digest('hex')
|
|
339
329
|
.toLowerCase() +
|
|
340
330
|
'?d=identicon&s=40'
|
|
@@ -373,7 +363,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
373
363
|
|
|
374
364
|
if (
|
|
375
365
|
incoming.includes('system/admin') !==
|
|
376
|
-
this
|
|
366
|
+
this.abilities?.includes('system/admin') &&
|
|
377
367
|
(!tilmeld.currentUser ||
|
|
378
368
|
!tilmeld.currentUser.abilities?.includes('system/admin'))
|
|
379
369
|
) {
|
|
@@ -384,7 +374,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
384
374
|
|
|
385
375
|
if (
|
|
386
376
|
incoming.includes('tilmeld/admin') !==
|
|
387
|
-
this
|
|
377
|
+
this.abilities?.includes('tilmeld/admin') &&
|
|
388
378
|
(!tilmeld.currentUser ||
|
|
389
379
|
!tilmeld.currentUser.abilities?.includes('system/admin'))
|
|
390
380
|
) {
|
|
@@ -395,7 +385,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
395
385
|
|
|
396
386
|
if (
|
|
397
387
|
incoming.includes('tilmeld/switch') !==
|
|
398
|
-
this
|
|
388
|
+
this.abilities?.includes('tilmeld/switch') &&
|
|
399
389
|
(!tilmeld.currentUser ||
|
|
400
390
|
!tilmeld.currentUser.abilities?.includes('system/admin'))
|
|
401
391
|
) {
|
|
@@ -407,7 +397,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
407
397
|
if (
|
|
408
398
|
xor(
|
|
409
399
|
incoming.filter((ability: string) => ability.startsWith('tilmeld/')),
|
|
410
|
-
this
|
|
400
|
+
this.abilities?.filter((ability: string) =>
|
|
411
401
|
ability.startsWith('tilmeld/'),
|
|
412
402
|
) ?? [],
|
|
413
403
|
).length &&
|
|
@@ -422,20 +412,20 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
422
412
|
}
|
|
423
413
|
|
|
424
414
|
public $putData(
|
|
425
|
-
data:
|
|
415
|
+
data: GroupData,
|
|
426
416
|
sdata?: SerializedEntityData,
|
|
427
417
|
source?: 'server',
|
|
428
418
|
) {
|
|
429
419
|
super.$putData(data, sdata, source);
|
|
430
420
|
// TODO: Fix these being added by the drivers.
|
|
431
421
|
// @ts-ignore
|
|
432
|
-
delete this
|
|
422
|
+
delete this.acRead;
|
|
433
423
|
// @ts-ignore
|
|
434
|
-
delete this
|
|
424
|
+
delete this.acWrite;
|
|
435
425
|
// @ts-ignore
|
|
436
|
-
delete this
|
|
426
|
+
delete this.acFull;
|
|
437
427
|
if (source === 'server') {
|
|
438
|
-
this.$originalGroupname = this
|
|
428
|
+
this.$originalGroupname = this.groupname;
|
|
439
429
|
}
|
|
440
430
|
this.$updateDataProtection();
|
|
441
431
|
}
|
|
@@ -445,12 +435,12 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
445
435
|
*
|
|
446
436
|
* @param givenUser User to update protection for. If undefined, will use the currently logged in user.
|
|
447
437
|
*/
|
|
448
|
-
public $updateDataProtection(givenUser?: UserClass
|
|
438
|
+
public $updateDataProtection(givenUser?: UserClass) {
|
|
449
439
|
const tilmeld = enforceTilmeld(this);
|
|
450
440
|
let user = givenUser ?? tilmeld.User.current();
|
|
451
441
|
let [_groupname, domain] = tilmeld.config.domainSupport
|
|
452
|
-
? splitn(this
|
|
453
|
-
: [this
|
|
442
|
+
? splitn(this.groupname ?? '', '@', 2)
|
|
443
|
+
: [this.groupname, null];
|
|
454
444
|
// Lowercase the domain part.
|
|
455
445
|
if (domain) {
|
|
456
446
|
domain = domain.toLowerCase();
|
|
@@ -472,9 +462,9 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
472
462
|
this.$privateData = [];
|
|
473
463
|
this.$allowlistData = undefined;
|
|
474
464
|
} else if (
|
|
475
|
-
this
|
|
465
|
+
this.user != null &&
|
|
476
466
|
user != null &&
|
|
477
|
-
this
|
|
467
|
+
this.user.guid === user.guid
|
|
478
468
|
) {
|
|
479
469
|
// Users can see their group's data.
|
|
480
470
|
this.$privateData = [];
|
|
@@ -495,11 +485,9 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
495
485
|
* @param group The group, or the group's GUID.
|
|
496
486
|
* @returns True or false.
|
|
497
487
|
*/
|
|
498
|
-
public async $isDescendant(
|
|
499
|
-
givenGroup: (Group & GroupData) | string,
|
|
500
|
-
): Promise<boolean> {
|
|
488
|
+
public async $isDescendant(givenGroup: Group | string): Promise<boolean> {
|
|
501
489
|
const tilmeld = enforceTilmeld(this);
|
|
502
|
-
let group: Group
|
|
490
|
+
let group: Group;
|
|
503
491
|
if (typeof givenGroup === 'string') {
|
|
504
492
|
group = await tilmeld.Group.factory(givenGroup);
|
|
505
493
|
} else {
|
|
@@ -509,7 +497,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
509
497
|
return false;
|
|
510
498
|
}
|
|
511
499
|
// Check to see if the group is a descendant of the given group.
|
|
512
|
-
const parent = this
|
|
500
|
+
const parent = this.parent;
|
|
513
501
|
await parent?.$wake();
|
|
514
502
|
if (parent == null) {
|
|
515
503
|
return false;
|
|
@@ -528,7 +516,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
528
516
|
*
|
|
529
517
|
* @returns An array of groups.
|
|
530
518
|
*/
|
|
531
|
-
public async $getChildren(): Promise<
|
|
519
|
+
public async $getChildren(): Promise<Group[]> {
|
|
532
520
|
const tilmeld = enforceTilmeld(this);
|
|
533
521
|
return await this.$nymph.getEntities(
|
|
534
522
|
{ class: tilmeld.Group },
|
|
@@ -550,9 +538,9 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
550
538
|
public async $getDescendants(
|
|
551
539
|
andSelf = false,
|
|
552
540
|
andDisabled = false,
|
|
553
|
-
): Promise<
|
|
541
|
+
): Promise<Group[]> {
|
|
554
542
|
const tilmeld = enforceTilmeld(this);
|
|
555
|
-
let groups:
|
|
543
|
+
let groups: Group[] = [];
|
|
556
544
|
const entities = await this.$nymph.getEntities(
|
|
557
545
|
{ class: tilmeld.Group },
|
|
558
546
|
{
|
|
@@ -608,9 +596,9 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
608
596
|
descendants = false,
|
|
609
597
|
limit?: number,
|
|
610
598
|
offset?: number,
|
|
611
|
-
): Promise<
|
|
599
|
+
): Promise<UserClass[]> {
|
|
612
600
|
const tilmeld = enforceTilmeld(this);
|
|
613
|
-
let groups:
|
|
601
|
+
let groups: Group[] = [];
|
|
614
602
|
if (descendants) {
|
|
615
603
|
groups = await this.$getDescendants();
|
|
616
604
|
}
|
|
@@ -626,14 +614,8 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
626
614
|
ref: [
|
|
627
615
|
['group', this],
|
|
628
616
|
['groups', this],
|
|
629
|
-
...groups.map((group): [string, Group
|
|
630
|
-
|
|
631
|
-
group,
|
|
632
|
-
]),
|
|
633
|
-
...groups.map((group): [string, Group & GroupData] => [
|
|
634
|
-
'groups',
|
|
635
|
-
group,
|
|
636
|
-
]),
|
|
617
|
+
...groups.map((group): [string, Group] => ['group', group]),
|
|
618
|
+
...groups.map((group): [string, Group] => ['groups', group]),
|
|
637
619
|
],
|
|
638
620
|
},
|
|
639
621
|
);
|
|
@@ -651,18 +633,18 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
651
633
|
const tilmeld = enforceTilmeld(this);
|
|
652
634
|
if (!tilmeld.config.emailUsernames) {
|
|
653
635
|
let [groupname, domain] = tilmeld.config.domainSupport
|
|
654
|
-
? splitn(this
|
|
655
|
-
: [this
|
|
636
|
+
? splitn(this.groupname ?? '', '@', 2)
|
|
637
|
+
: [this.groupname, null];
|
|
656
638
|
|
|
657
639
|
// Lowercase the domain part.
|
|
658
640
|
if (domain) {
|
|
659
641
|
domain = domain.toLowerCase();
|
|
660
|
-
this
|
|
642
|
+
this.groupname = `${groupname}@${domain}`;
|
|
661
643
|
}
|
|
662
644
|
|
|
663
645
|
if (
|
|
664
|
-
this
|
|
665
|
-
!this
|
|
646
|
+
this.groupname == null ||
|
|
647
|
+
!this.groupname.length ||
|
|
666
648
|
groupname == null ||
|
|
667
649
|
!groupname.length
|
|
668
650
|
) {
|
|
@@ -724,7 +706,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
724
706
|
type: '&',
|
|
725
707
|
ilike: [
|
|
726
708
|
'groupname',
|
|
727
|
-
this
|
|
709
|
+
this.groupname.replace(/([\\%_])/g, (s) => `\\${s}`),
|
|
728
710
|
],
|
|
729
711
|
};
|
|
730
712
|
if (this.guid != null) {
|
|
@@ -742,7 +724,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
742
724
|
.checkGroupnameCallbacks) {
|
|
743
725
|
if (callback) {
|
|
744
726
|
const result = await callback(this, {
|
|
745
|
-
groupname: this
|
|
727
|
+
groupname: this.groupname,
|
|
746
728
|
});
|
|
747
729
|
if (!result.result) {
|
|
748
730
|
return { message: 'Groupname is not available.', ...result };
|
|
@@ -756,11 +738,11 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
756
738
|
this.guid != null ? 'Groupname is valid.' : 'Groupname is available!',
|
|
757
739
|
};
|
|
758
740
|
} else {
|
|
759
|
-
this
|
|
760
|
-
if (this
|
|
741
|
+
this.email = this.groupname;
|
|
742
|
+
if (this.groupname == null || !this.groupname.length) {
|
|
761
743
|
return { result: false, message: 'Please specify an email.' };
|
|
762
744
|
}
|
|
763
|
-
if (this
|
|
745
|
+
if (this.groupname.length < tilmeld.config.minUsernameLength) {
|
|
764
746
|
return {
|
|
765
747
|
result: false,
|
|
766
748
|
message:
|
|
@@ -769,7 +751,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
769
751
|
' characters.',
|
|
770
752
|
};
|
|
771
753
|
}
|
|
772
|
-
if (this
|
|
754
|
+
if (this.groupname.length > tilmeld.config.maxUsernameLength) {
|
|
773
755
|
return {
|
|
774
756
|
result: false,
|
|
775
757
|
message:
|
|
@@ -790,13 +772,13 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
790
772
|
*/
|
|
791
773
|
public async $checkEmail(): Promise<{ result: boolean; message: string }> {
|
|
792
774
|
const tilmeld = enforceTilmeld(this);
|
|
793
|
-
if (this
|
|
775
|
+
if (this.email === '') {
|
|
794
776
|
return { result: true, message: '' };
|
|
795
777
|
}
|
|
796
|
-
if (this
|
|
778
|
+
if (this.email == null) {
|
|
797
779
|
return { result: false, message: 'Please specify a valid email.' };
|
|
798
780
|
}
|
|
799
|
-
if (!tilmeld.config.validEmailRegex.test(this
|
|
781
|
+
if (!tilmeld.config.validEmailRegex.test(this.email)) {
|
|
800
782
|
return {
|
|
801
783
|
result: false,
|
|
802
784
|
message: tilmeld.config.validEmailRegexNotice,
|
|
@@ -804,7 +786,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
804
786
|
}
|
|
805
787
|
const selector: Selector = {
|
|
806
788
|
type: '&',
|
|
807
|
-
ilike: ['email', this
|
|
789
|
+
ilike: ['email', this.email.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
808
790
|
};
|
|
809
791
|
if (this.guid != null) {
|
|
810
792
|
selector['!guid'] = this.guid;
|
|
@@ -829,20 +811,20 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
829
811
|
|
|
830
812
|
public async $save() {
|
|
831
813
|
let tilmeld = enforceTilmeld(this);
|
|
832
|
-
if (this
|
|
814
|
+
if (this.groupname == null || !this.groupname.trim().length) {
|
|
833
815
|
throw new BadUsernameError('Groupname must not be empty.');
|
|
834
816
|
}
|
|
835
817
|
|
|
836
818
|
// Lowercase the domain part.
|
|
837
819
|
if (tilmeld.config.domainSupport) {
|
|
838
|
-
const [groupname, domain] = splitn(this
|
|
820
|
+
const [groupname, domain] = splitn(this.groupname ?? '', '@', 2);
|
|
839
821
|
if (domain) {
|
|
840
|
-
this
|
|
822
|
+
this.groupname = `${groupname}@${domain.toLowerCase()}`;
|
|
841
823
|
}
|
|
842
824
|
}
|
|
843
825
|
|
|
844
826
|
if (tilmeld.config.domainSupport) {
|
|
845
|
-
const [_groupname, domain] = splitn(this
|
|
827
|
+
const [_groupname, domain] = splitn(this.groupname ?? '', '@', 2);
|
|
846
828
|
const [_originalGroupname, originalDomain] = splitn(
|
|
847
829
|
this.$originalGroupname ?? '',
|
|
848
830
|
'@',
|
|
@@ -887,53 +869,47 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
887
869
|
}
|
|
888
870
|
|
|
889
871
|
// Formatting.
|
|
890
|
-
this
|
|
872
|
+
this.groupname = this.groupname.trim();
|
|
891
873
|
if (tilmeld.config.emailUsernames) {
|
|
892
|
-
this
|
|
874
|
+
this.email = this.groupname;
|
|
893
875
|
}
|
|
894
|
-
this
|
|
895
|
-
this
|
|
896
|
-
this
|
|
897
|
-
this
|
|
876
|
+
this.email = (this.email ?? '').trim();
|
|
877
|
+
this.name = (this.name ?? '').trim();
|
|
878
|
+
this.phone = (this.phone ?? '').trim();
|
|
879
|
+
this.enabled = !!this.enabled;
|
|
898
880
|
|
|
899
881
|
// Clear empty values.
|
|
900
|
-
if (this
|
|
901
|
-
delete this
|
|
882
|
+
if (this.name === '' || !tilmeld.config.userFields.includes('name')) {
|
|
883
|
+
delete this.name;
|
|
902
884
|
}
|
|
903
|
-
if (
|
|
904
|
-
this
|
|
905
|
-
!tilmeld.config.userFields.includes('email')
|
|
906
|
-
) {
|
|
907
|
-
delete this.$data.email;
|
|
885
|
+
if (this.email === '' || !tilmeld.config.userFields.includes('email')) {
|
|
886
|
+
delete this.email;
|
|
908
887
|
}
|
|
909
|
-
if (this
|
|
910
|
-
delete this
|
|
888
|
+
if (this.avatar === '') {
|
|
889
|
+
delete this.avatar;
|
|
911
890
|
}
|
|
912
|
-
if (
|
|
913
|
-
this
|
|
914
|
-
!tilmeld.config.userFields.includes('phone')
|
|
915
|
-
) {
|
|
916
|
-
delete this.$data.phone;
|
|
891
|
+
if (this.phone === '' || !tilmeld.config.userFields.includes('phone')) {
|
|
892
|
+
delete this.phone;
|
|
917
893
|
}
|
|
918
|
-
if (this
|
|
919
|
-
delete this
|
|
894
|
+
if (this.parent == null) {
|
|
895
|
+
delete this.parent;
|
|
920
896
|
}
|
|
921
|
-
if (this
|
|
922
|
-
delete this
|
|
897
|
+
if (this.user == null) {
|
|
898
|
+
delete this.user;
|
|
923
899
|
}
|
|
924
|
-
if (!this
|
|
925
|
-
delete this
|
|
900
|
+
if (!this.defaultPrimary) {
|
|
901
|
+
delete this.defaultPrimary;
|
|
926
902
|
}
|
|
927
|
-
if (!this
|
|
928
|
-
delete this
|
|
903
|
+
if (!this.defaultSecondary) {
|
|
904
|
+
delete this.defaultSecondary;
|
|
929
905
|
}
|
|
930
|
-
if (!this
|
|
931
|
-
delete this
|
|
906
|
+
if (!this.unverifiedSecondary) {
|
|
907
|
+
delete this.unverifiedSecondary;
|
|
932
908
|
}
|
|
933
909
|
|
|
934
910
|
// Groups should never have 'system/admin', 'tilmeld/admin',
|
|
935
911
|
// 'tilmeld/switch', or domain admin abilities.
|
|
936
|
-
this
|
|
912
|
+
this.abilities = (this.abilities ?? []).filter((ability) => {
|
|
937
913
|
if (
|
|
938
914
|
['system/admin', 'tilmeld/admin', 'tilmeld/switch'].indexOf(ability) !==
|
|
939
915
|
-1
|
|
@@ -965,7 +941,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
965
941
|
}
|
|
966
942
|
|
|
967
943
|
// Validate group parent. Make sure it's not a descendant of this group.
|
|
968
|
-
const parent = this
|
|
944
|
+
const parent = this.parent;
|
|
969
945
|
await parent?.$wake();
|
|
970
946
|
if (
|
|
971
947
|
parent &&
|
|
@@ -985,7 +961,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
985
961
|
}
|
|
986
962
|
|
|
987
963
|
// Only one default primary group is allowed.
|
|
988
|
-
if (this
|
|
964
|
+
if (this.defaultPrimary) {
|
|
989
965
|
const currentPrimary = await this.$nymph.getEntity(
|
|
990
966
|
{ class: tilmeld.Group },
|
|
991
967
|
{ type: '&', truthy: 'defaultPrimary' },
|
|
@@ -1036,7 +1012,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
1036
1012
|
this.$setNymph(nymph);
|
|
1037
1013
|
|
|
1038
1014
|
if (committed) {
|
|
1039
|
-
this.$originalGroupname = this
|
|
1015
|
+
this.$originalGroupname = this.groupname;
|
|
1040
1016
|
} else {
|
|
1041
1017
|
this.guid = preGuid;
|
|
1042
1018
|
this.cdate = preCdate;
|
|
@@ -1072,7 +1048,7 @@ export default class Group extends AbleObject<GroupData> {
|
|
|
1072
1048
|
"You don't have the authority to delete groups.",
|
|
1073
1049
|
);
|
|
1074
1050
|
}
|
|
1075
|
-
if (this
|
|
1051
|
+
if (this.groupname !== this.$originalGroupname) {
|
|
1076
1052
|
throw new AccessControlError(
|
|
1077
1053
|
"You can't delete a group while switching its groupname.",
|
|
1078
1054
|
);
|