@nymphjs/tilmeld 1.0.0-alpha.1 → 1.0.0-alpha.5
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 +26 -0
- package/README.md +15 -10
- package/dist/Group.d.ts +2 -0
- package/dist/Group.js +68 -59
- package/dist/Group.js.map +1 -1
- package/dist/Group.test.js +12 -7
- package/dist/Group.test.js.map +1 -1
- package/dist/Tilmeld.d.ts +26 -22
- package/dist/Tilmeld.js +172 -92
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +2 -0
- package/dist/User.js +134 -122
- package/dist/User.js.map +1 -1
- package/dist/User.test.js +12 -7
- package/dist/User.test.js.map +1 -1
- package/dist/conf/d.d.ts +7 -3
- package/dist/conf/defaults.js +41 -109
- package/dist/conf/defaults.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- 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 +6 -6
- package/src/Group.test.ts +18 -7
- package/src/Group.ts +88 -64
- package/src/Tilmeld.ts +284 -116
- package/src/User.test.ts +18 -7
- package/src/User.ts +164 -125
- package/src/conf/d.ts +38 -2
- package/src/conf/defaults.ts +29 -68
- package/src/index.ts +3 -1
- package/src/tilmeldJoiProps.ts +46 -0
package/src/User.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
2
|
EntityData,
|
|
3
3
|
EntityJson,
|
|
4
4
|
EntityPatch,
|
|
@@ -14,9 +14,9 @@ import sha256 from 'crypto-js/sha256';
|
|
|
14
14
|
import md5 from 'crypto-js/md5';
|
|
15
15
|
import { difference } from 'lodash';
|
|
16
16
|
|
|
17
|
+
import type Tilmeld from './Tilmeld';
|
|
17
18
|
import AbleObject from './AbleObject';
|
|
18
19
|
import Group, { GroupData } from './Group';
|
|
19
|
-
import Tilmeld from './Tilmeld';
|
|
20
20
|
import {
|
|
21
21
|
BadDataError,
|
|
22
22
|
BadEmailError,
|
|
@@ -126,7 +126,20 @@ export type UserData = {
|
|
|
126
126
|
passwordTemp?: string;
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
/**
|
|
130
|
+
* A user data model.
|
|
131
|
+
*
|
|
132
|
+
* Written by Hunter Perrin for SciActive.
|
|
133
|
+
*
|
|
134
|
+
* @author Hunter Perrin <hperrin@gmail.com>
|
|
135
|
+
* @copyright SciActive Inc
|
|
136
|
+
* @see http://nymph.io/
|
|
137
|
+
*/
|
|
129
138
|
export default class User extends AbleObject<UserData> {
|
|
139
|
+
/**
|
|
140
|
+
* The instance of Tilmeld to use for queries.
|
|
141
|
+
*/
|
|
142
|
+
static tilmeld: Tilmeld;
|
|
130
143
|
static ETYPE = 'tilmeld_user';
|
|
131
144
|
static class = 'User';
|
|
132
145
|
|
|
@@ -202,7 +215,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
202
215
|
static async factoryUsername(username?: string): Promise<User & UserData> {
|
|
203
216
|
const entity = new this();
|
|
204
217
|
if (username != null) {
|
|
205
|
-
const entity = await
|
|
218
|
+
const entity = await this.nymph.getEntity(
|
|
206
219
|
{
|
|
207
220
|
class: this,
|
|
208
221
|
},
|
|
@@ -242,10 +255,10 @@ export default class User extends AbleObject<UserData> {
|
|
|
242
255
|
public static current(
|
|
243
256
|
returnObjectIfNotExist?: boolean
|
|
244
257
|
): (User & UserData) | null {
|
|
245
|
-
if (
|
|
258
|
+
if (this.tilmeld.currentUser == null) {
|
|
246
259
|
return returnObjectIfNotExist ? this.factorySync() : null;
|
|
247
260
|
}
|
|
248
|
-
return
|
|
261
|
+
return this.tilmeld.currentUser;
|
|
249
262
|
}
|
|
250
263
|
|
|
251
264
|
/**
|
|
@@ -258,7 +271,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
258
271
|
recoveryType: 'username' | 'password';
|
|
259
272
|
account: string;
|
|
260
273
|
}): Promise<{ result: boolean; message: string }> {
|
|
261
|
-
if (!
|
|
274
|
+
if (!this.tilmeld.config.pwRecovery) {
|
|
262
275
|
return {
|
|
263
276
|
result: false,
|
|
264
277
|
message: 'Account recovery is not allowed.',
|
|
@@ -268,11 +281,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
268
281
|
let user: User & UserData;
|
|
269
282
|
const options: EmailOptions = {};
|
|
270
283
|
|
|
271
|
-
if (
|
|
284
|
+
if (
|
|
285
|
+
!this.tilmeld.config.emailUsernames &&
|
|
286
|
+
data.recoveryType === 'username'
|
|
287
|
+
) {
|
|
272
288
|
// Create a username recovery email.
|
|
273
289
|
|
|
274
|
-
const getUser = await
|
|
275
|
-
{ class: User, skipAc: true },
|
|
290
|
+
const getUser = await this.nymph.getEntity(
|
|
291
|
+
{ class: this.tilmeld.User, skipAc: true },
|
|
276
292
|
{
|
|
277
293
|
type: '&',
|
|
278
294
|
ilike: ['email', data.account.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
@@ -299,7 +315,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
299
315
|
} else if (data.recoveryType === 'password') {
|
|
300
316
|
// Create a password recovery email.
|
|
301
317
|
|
|
302
|
-
const getUser = await User.factoryUsername(data.account);
|
|
318
|
+
const getUser = await this.tilmeld.User.factoryUsername(data.account);
|
|
303
319
|
|
|
304
320
|
if (getUser.guid == null) {
|
|
305
321
|
return {
|
|
@@ -326,14 +342,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
326
342
|
};
|
|
327
343
|
options.locals = {
|
|
328
344
|
recoverCode: getUser.recoverSecret,
|
|
329
|
-
timeLimit:
|
|
345
|
+
timeLimit: this.tilmeld.config.pwRecoveryTimeLimit,
|
|
330
346
|
};
|
|
331
347
|
} else {
|
|
332
348
|
return { result: false, message: 'Invalid recovery type.' };
|
|
333
349
|
}
|
|
334
350
|
|
|
335
351
|
// Send the email.
|
|
336
|
-
if (await
|
|
352
|
+
if (await this.tilmeld.config.sendEmail(this.tilmeld, options, user)) {
|
|
337
353
|
return {
|
|
338
354
|
result: true,
|
|
339
355
|
message:
|
|
@@ -356,21 +372,21 @@ export default class User extends AbleObject<UserData> {
|
|
|
356
372
|
secret: string;
|
|
357
373
|
password: string;
|
|
358
374
|
}): Promise<{ result: boolean; message: string }> {
|
|
359
|
-
if (!
|
|
375
|
+
if (!this.tilmeld.config.pwRecovery) {
|
|
360
376
|
return {
|
|
361
377
|
result: false,
|
|
362
378
|
message: 'Account recovery is not allowed.',
|
|
363
379
|
};
|
|
364
380
|
}
|
|
365
381
|
|
|
366
|
-
const user = await User.factoryUsername(data.username);
|
|
382
|
+
const user = await this.tilmeld.User.factoryUsername(data.username);
|
|
367
383
|
|
|
368
384
|
if (
|
|
369
385
|
user.guid == null ||
|
|
370
386
|
user.recoverSecret == null ||
|
|
371
387
|
data.secret !== user.recoverSecret ||
|
|
372
388
|
strtotime(
|
|
373
|
-
'+' +
|
|
389
|
+
'+' + this.tilmeld.config.pwRecoveryTimeLimit,
|
|
374
390
|
Math.floor((user.recoverSecretDate ?? 0) / 1000)
|
|
375
391
|
) *
|
|
376
392
|
1000 <
|
|
@@ -402,14 +418,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
402
418
|
|
|
403
419
|
public static getClientConfig() {
|
|
404
420
|
return {
|
|
405
|
-
regFields:
|
|
406
|
-
userFields:
|
|
407
|
-
emailUsernames:
|
|
408
|
-
allowRegistration:
|
|
409
|
-
allowUsernameChange:
|
|
410
|
-
pwRecovery:
|
|
411
|
-
verifyEmail:
|
|
412
|
-
unverifiedAccess:
|
|
421
|
+
regFields: this.tilmeld.config.regFields,
|
|
422
|
+
userFields: this.tilmeld.config.userFields,
|
|
423
|
+
emailUsernames: this.tilmeld.config.emailUsernames,
|
|
424
|
+
allowRegistration: this.tilmeld.config.allowRegistration,
|
|
425
|
+
allowUsernameChange: this.tilmeld.config.allowUsernameChange,
|
|
426
|
+
pwRecovery: this.tilmeld.config.pwRecovery,
|
|
427
|
+
verifyEmail: this.tilmeld.config.verifyEmail,
|
|
428
|
+
unverifiedAccess: this.tilmeld.config.unverifiedAccess,
|
|
413
429
|
};
|
|
414
430
|
}
|
|
415
431
|
|
|
@@ -417,7 +433,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
417
433
|
if (!('username' in data) || !data.username.length) {
|
|
418
434
|
return { result: false, message: 'Incorrect login/password.' };
|
|
419
435
|
}
|
|
420
|
-
const user = await User.factoryUsername(data.username);
|
|
436
|
+
const user = await this.tilmeld.User.factoryUsername(data.username);
|
|
421
437
|
const result: { result: boolean; message: string; user?: User & UserData } =
|
|
422
438
|
user.$login(data);
|
|
423
439
|
if (result.result) {
|
|
@@ -428,6 +444,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
428
444
|
}
|
|
429
445
|
|
|
430
446
|
public $login(data: { username: string; password: string }) {
|
|
447
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
431
448
|
if (this.guid == null) {
|
|
432
449
|
return { result: false, message: 'Incorrect login/password.' };
|
|
433
450
|
}
|
|
@@ -442,7 +459,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
442
459
|
}
|
|
443
460
|
|
|
444
461
|
// Authentication was successful, attempt to login.
|
|
445
|
-
if (!
|
|
462
|
+
if (!tilmeld.login(this, true)) {
|
|
446
463
|
return { result: false, message: 'Incorrect login/password.' };
|
|
447
464
|
}
|
|
448
465
|
|
|
@@ -455,7 +472,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
455
472
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
456
473
|
*/
|
|
457
474
|
public $logout() {
|
|
458
|
-
Tilmeld
|
|
475
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
476
|
+
tilmeld.logout();
|
|
459
477
|
return { result: true, message: 'You have been logged out.' };
|
|
460
478
|
}
|
|
461
479
|
|
|
@@ -510,13 +528,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
510
528
|
}
|
|
511
529
|
|
|
512
530
|
public $jsonAcceptData(input: EntityJson, allowConflict = false) {
|
|
531
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
513
532
|
this.$referenceWake();
|
|
514
533
|
|
|
515
534
|
if (
|
|
516
|
-
input.data.abilities
|
|
535
|
+
input.data.abilities?.indexOf('system/admin') !== -1 &&
|
|
517
536
|
this.$data.abilities?.indexOf('system/admin') === -1 &&
|
|
518
|
-
|
|
519
|
-
!
|
|
537
|
+
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
538
|
+
!tilmeld.gatekeeper('system/admin')
|
|
520
539
|
) {
|
|
521
540
|
throw new BadDataError(
|
|
522
541
|
"You don't have the authority to make this user a system admin."
|
|
@@ -528,13 +547,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
528
547
|
}
|
|
529
548
|
|
|
530
549
|
public $jsonAcceptPatch(patch: EntityPatch, allowConflict = false) {
|
|
550
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
531
551
|
this.$referenceWake();
|
|
532
552
|
|
|
533
553
|
if (
|
|
534
|
-
patch.set.abilities
|
|
554
|
+
patch.set.abilities?.indexOf('system/admin') !== -1 &&
|
|
535
555
|
this.$data.abilities?.indexOf('system/admin') === -1 &&
|
|
536
|
-
|
|
537
|
-
!
|
|
556
|
+
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
557
|
+
!tilmeld.gatekeeper('system/admin')
|
|
538
558
|
) {
|
|
539
559
|
throw new BadDataError(
|
|
540
560
|
"You don't have the authority to make this user a system admin."
|
|
@@ -556,13 +576,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
556
576
|
* @param givenUser User to update protection for. If undefined, will use the currently logged in user.
|
|
557
577
|
*/
|
|
558
578
|
public $updateDataProtection(givenUser?: User & UserData) {
|
|
559
|
-
|
|
579
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
580
|
+
let user = givenUser ?? tilmeld.User.current();
|
|
560
581
|
|
|
561
582
|
this.$clientEnabledMethods = User.DEFAULT_CLIENT_ENABLED_METHODS;
|
|
562
583
|
this.$privateData = User.DEFAULT_PRIVATE_DATA;
|
|
563
584
|
this.$allowlistData = User.DEFAULT_ALLOWLIST_DATA;
|
|
564
585
|
|
|
565
|
-
if (
|
|
586
|
+
if (tilmeld.config.emailUsernames) {
|
|
566
587
|
this.$privateData.push('username');
|
|
567
588
|
}
|
|
568
589
|
|
|
@@ -593,20 +614,20 @@ export default class User extends AbleObject<UserData> {
|
|
|
593
614
|
this.$allowlistData = undefined;
|
|
594
615
|
} else if (isCurrentUser || isNewUser) {
|
|
595
616
|
// Users can see their own data, and edit some of it.
|
|
596
|
-
if (
|
|
617
|
+
if (tilmeld.config.allowUsernameChange || isNewUser) {
|
|
597
618
|
this.$allowlistData.push('username');
|
|
598
619
|
}
|
|
599
620
|
this.$allowlistData.push('avatar');
|
|
600
|
-
if (
|
|
621
|
+
if (tilmeld.config.userFields.indexOf('name') !== -1) {
|
|
601
622
|
this.$allowlistData.push('nameFirst');
|
|
602
623
|
this.$allowlistData.push('nameMiddle');
|
|
603
624
|
this.$allowlistData.push('nameLast');
|
|
604
625
|
this.$allowlistData.push('name');
|
|
605
626
|
}
|
|
606
|
-
if (
|
|
627
|
+
if (tilmeld.config.userFields.indexOf('email') !== -1) {
|
|
607
628
|
this.$allowlistData.push('email');
|
|
608
629
|
}
|
|
609
|
-
if (
|
|
630
|
+
if (tilmeld.config.userFields.indexOf('phone') !== -1) {
|
|
610
631
|
this.$allowlistData.push('phone');
|
|
611
632
|
}
|
|
612
633
|
this.$privateData = [
|
|
@@ -638,8 +659,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
638
659
|
* @returns True or false.
|
|
639
660
|
*/
|
|
640
661
|
public $gatekeeper(ability?: string): boolean {
|
|
662
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
641
663
|
if (ability == null) {
|
|
642
|
-
return User.current()?.$is(this) ?? false;
|
|
664
|
+
return tilmeld.User.current()?.$is(this) ?? false;
|
|
643
665
|
}
|
|
644
666
|
// Check the cache to see if we've already checked this user.
|
|
645
667
|
if (this.$gatekeeperCache == null) {
|
|
@@ -681,13 +703,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
681
703
|
* @returns True on success, false on failure.
|
|
682
704
|
*/
|
|
683
705
|
public async $sendEmailVerification() {
|
|
706
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
684
707
|
if (this.guid == null) {
|
|
685
708
|
return false;
|
|
686
709
|
}
|
|
687
710
|
let success = true;
|
|
688
711
|
|
|
689
|
-
const verifyUrl = `${
|
|
690
|
-
|
|
712
|
+
const verifyUrl = `${tilmeld.config.appUrl.replace(/\/$/, () => '')}${
|
|
713
|
+
tilmeld.config.setupPath
|
|
691
714
|
}/verify`;
|
|
692
715
|
|
|
693
716
|
if (this.$data.secret != null) {
|
|
@@ -696,7 +719,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
696
719
|
)}&secret=${encodeURIComponent(this.$data.secret)}`;
|
|
697
720
|
success =
|
|
698
721
|
success &&
|
|
699
|
-
(await
|
|
722
|
+
(await tilmeld.config.sendEmail(
|
|
723
|
+
tilmeld,
|
|
700
724
|
{
|
|
701
725
|
template: 'VerifyEmail',
|
|
702
726
|
message: {
|
|
@@ -719,7 +743,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
719
743
|
)}&secret=${encodeURIComponent(this.$data.newEmailSecret)}`;
|
|
720
744
|
success =
|
|
721
745
|
success &&
|
|
722
|
-
(await
|
|
746
|
+
(await tilmeld.config.sendEmail(
|
|
747
|
+
tilmeld,
|
|
723
748
|
{
|
|
724
749
|
template: 'VerifyEmailChange',
|
|
725
750
|
message: {
|
|
@@ -744,7 +769,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
744
769
|
)}&secret=${encodeURIComponent(this.$data.cancelEmailSecret)}`;
|
|
745
770
|
success =
|
|
746
771
|
success &&
|
|
747
|
-
(await
|
|
772
|
+
(await tilmeld.config.sendEmail(
|
|
773
|
+
tilmeld,
|
|
748
774
|
{
|
|
749
775
|
template: 'CancelEmailChange',
|
|
750
776
|
message: {
|
|
@@ -790,7 +816,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
790
816
|
* @returns True if the passwords match, otherwise false.
|
|
791
817
|
*/
|
|
792
818
|
public $checkPassword(password: string) {
|
|
793
|
-
|
|
819
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
820
|
+
switch (tilmeld.config.pwMethod) {
|
|
794
821
|
case 'plain':
|
|
795
822
|
return this.$data.password === password;
|
|
796
823
|
case 'digest':
|
|
@@ -900,7 +927,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
900
927
|
* @returns The resulting password or hash which is stored in the entity.
|
|
901
928
|
*/
|
|
902
929
|
public $password(password: string) {
|
|
903
|
-
|
|
930
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
931
|
+
switch (tilmeld.config.pwMethod) {
|
|
904
932
|
case 'plain':
|
|
905
933
|
delete this.$data.salt;
|
|
906
934
|
this.$data.password = password;
|
|
@@ -926,19 +954,20 @@ export default class User extends AbleObject<UserData> {
|
|
|
926
954
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
927
955
|
*/
|
|
928
956
|
public async $checkUsername(): Promise<{ result: boolean; message: string }> {
|
|
929
|
-
|
|
957
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
958
|
+
if (!tilmeld.config.emailUsernames) {
|
|
930
959
|
if (this.$data.username == null || !this.$data.username.length) {
|
|
931
960
|
return { result: false, message: 'Please specify a username.' };
|
|
932
961
|
}
|
|
933
962
|
if (
|
|
934
|
-
|
|
935
|
-
this.$data.username.length >
|
|
963
|
+
tilmeld.config.maxUsernameLength > 0 &&
|
|
964
|
+
this.$data.username.length > tilmeld.config.maxUsernameLength
|
|
936
965
|
) {
|
|
937
966
|
return {
|
|
938
967
|
result: false,
|
|
939
968
|
message:
|
|
940
969
|
'Usernames must not exceed ' +
|
|
941
|
-
|
|
970
|
+
tilmeld.config.maxUsernameLength +
|
|
942
971
|
' characters.',
|
|
943
972
|
};
|
|
944
973
|
}
|
|
@@ -946,18 +975,18 @@ export default class User extends AbleObject<UserData> {
|
|
|
946
975
|
if (
|
|
947
976
|
difference(
|
|
948
977
|
this.$data.username.split(''),
|
|
949
|
-
|
|
978
|
+
tilmeld.config.validChars.split('')
|
|
950
979
|
).length
|
|
951
980
|
) {
|
|
952
981
|
return {
|
|
953
982
|
result: false,
|
|
954
|
-
message:
|
|
983
|
+
message: tilmeld.config.validCharsNotice,
|
|
955
984
|
};
|
|
956
985
|
}
|
|
957
|
-
if (!
|
|
986
|
+
if (!tilmeld.config.validRegex.test(this.$data.username)) {
|
|
958
987
|
return {
|
|
959
988
|
result: false,
|
|
960
|
-
message:
|
|
989
|
+
message: tilmeld.config.validRegexNotice,
|
|
961
990
|
};
|
|
962
991
|
}
|
|
963
992
|
|
|
@@ -971,8 +1000,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
971
1000
|
if (this.guid != null) {
|
|
972
1001
|
selector['!guid'] = this.guid;
|
|
973
1002
|
}
|
|
974
|
-
const test = await
|
|
975
|
-
{ class: User, skipAc: true },
|
|
1003
|
+
const test = await this.$nymph.getEntity(
|
|
1004
|
+
{ class: tilmeld.User, skipAc: true },
|
|
976
1005
|
selector
|
|
977
1006
|
);
|
|
978
1007
|
if (test != null) {
|
|
@@ -990,14 +1019,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
990
1019
|
return { result: false, message: 'Please specify an email.' };
|
|
991
1020
|
}
|
|
992
1021
|
if (
|
|
993
|
-
|
|
994
|
-
this.$data.username.length >
|
|
1022
|
+
tilmeld.config.maxUsernameLength > 0 &&
|
|
1023
|
+
this.$data.username.length > tilmeld.config.maxUsernameLength
|
|
995
1024
|
) {
|
|
996
1025
|
return {
|
|
997
1026
|
result: false,
|
|
998
1027
|
message:
|
|
999
1028
|
'Emails must not exceed ' +
|
|
1000
|
-
|
|
1029
|
+
tilmeld.config.maxUsernameLength +
|
|
1001
1030
|
' characters.',
|
|
1002
1031
|
};
|
|
1003
1032
|
}
|
|
@@ -1012,17 +1041,18 @@ export default class User extends AbleObject<UserData> {
|
|
|
1012
1041
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
1013
1042
|
*/
|
|
1014
1043
|
public async $checkEmail(): Promise<{ result: boolean; message: string }> {
|
|
1044
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1015
1045
|
if (this.$data.email == null || !this.$data.email.length) {
|
|
1016
|
-
if (
|
|
1046
|
+
if (tilmeld.config.verifyEmail) {
|
|
1017
1047
|
return { result: false, message: 'Please specify an email.' };
|
|
1018
1048
|
} else {
|
|
1019
1049
|
return { result: true, message: '' };
|
|
1020
1050
|
}
|
|
1021
1051
|
}
|
|
1022
|
-
if (!
|
|
1052
|
+
if (!tilmeld.config.validEmailRegex.test(this.$data.email)) {
|
|
1023
1053
|
return {
|
|
1024
1054
|
result: false,
|
|
1025
|
-
message:
|
|
1055
|
+
message: tilmeld.config.validEmailRegexNotice,
|
|
1026
1056
|
};
|
|
1027
1057
|
}
|
|
1028
1058
|
const selector: Selector = {
|
|
@@ -1032,7 +1062,10 @@ export default class User extends AbleObject<UserData> {
|
|
|
1032
1062
|
if (this.guid != null) {
|
|
1033
1063
|
selector['!guid'] = this.guid;
|
|
1034
1064
|
}
|
|
1035
|
-
const test = await
|
|
1065
|
+
const test = await this.$nymph.getEntity(
|
|
1066
|
+
{ class: tilmeld.User, skipAc: true },
|
|
1067
|
+
selector
|
|
1068
|
+
);
|
|
1036
1069
|
if (test != null) {
|
|
1037
1070
|
return {
|
|
1038
1071
|
result: false,
|
|
@@ -1053,6 +1086,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1053
1086
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
1054
1087
|
*/
|
|
1055
1088
|
public async $checkPhone(): Promise<{ result: boolean; message: string }> {
|
|
1089
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1056
1090
|
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
1057
1091
|
return { result: false, message: 'Please specify a phone number.' };
|
|
1058
1092
|
}
|
|
@@ -1072,7 +1106,10 @@ export default class User extends AbleObject<UserData> {
|
|
|
1072
1106
|
if (this.guid != null) {
|
|
1073
1107
|
selector['!guid'] = this.guid;
|
|
1074
1108
|
}
|
|
1075
|
-
const test = await
|
|
1109
|
+
const test = await this.$nymph.getEntity(
|
|
1110
|
+
{ class: tilmeld.User, skipAc: true },
|
|
1111
|
+
selector
|
|
1112
|
+
);
|
|
1076
1113
|
if (test != null) {
|
|
1077
1114
|
return { result: false, message: 'Phone number is in use.' };
|
|
1078
1115
|
}
|
|
@@ -1087,7 +1124,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
1087
1124
|
public async $register(data: {
|
|
1088
1125
|
password: string;
|
|
1089
1126
|
}): Promise<{ result: boolean; loggedin: boolean; message: string }> {
|
|
1090
|
-
|
|
1127
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1128
|
+
if (!tilmeld.config.allowRegistration) {
|
|
1091
1129
|
return {
|
|
1092
1130
|
result: false,
|
|
1093
1131
|
loggedin: false,
|
|
@@ -1114,7 +1152,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1114
1152
|
}
|
|
1115
1153
|
|
|
1116
1154
|
this.$password(data.password);
|
|
1117
|
-
if (
|
|
1155
|
+
if (tilmeld.config.regFields.indexOf('name') !== -1) {
|
|
1118
1156
|
this.$data.name =
|
|
1119
1157
|
this.$data.nameFirst +
|
|
1120
1158
|
(this.$data.nameMiddle == null ? '' : ' ' + this.$data.nameMiddle) +
|
|
@@ -1123,26 +1161,26 @@ export default class User extends AbleObject<UserData> {
|
|
|
1123
1161
|
this.$data.name = this.$data.username;
|
|
1124
1162
|
}
|
|
1125
1163
|
}
|
|
1126
|
-
if (
|
|
1164
|
+
if (tilmeld.config.emailUsernames) {
|
|
1127
1165
|
this.$data.email = this.$data.username;
|
|
1128
1166
|
}
|
|
1129
1167
|
|
|
1130
1168
|
// Start transaction.
|
|
1131
1169
|
const transaction = 'tilmeld-register-' + nanoid();
|
|
1132
|
-
await
|
|
1170
|
+
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1133
1171
|
|
|
1134
1172
|
try {
|
|
1135
1173
|
// Add primary group.
|
|
1136
1174
|
let generatedPrimaryGroup: (Group & GroupData) | null = null;
|
|
1137
|
-
if (
|
|
1175
|
+
if (tilmeld.config.generatePrimary) {
|
|
1138
1176
|
// Generate a new primary group for the user.
|
|
1139
|
-
generatedPrimaryGroup = await Group.factory();
|
|
1177
|
+
generatedPrimaryGroup = await tilmeld.Group.factory();
|
|
1140
1178
|
generatedPrimaryGroup.groupname = this.$data.username;
|
|
1141
1179
|
generatedPrimaryGroup.avatar = this.$data.avatar;
|
|
1142
1180
|
generatedPrimaryGroup.name = this.$data.name;
|
|
1143
1181
|
generatedPrimaryGroup.email = this.$data.email;
|
|
1144
|
-
const parent = await
|
|
1145
|
-
{ class: Group },
|
|
1182
|
+
const parent = await tnymph.getEntity(
|
|
1183
|
+
{ class: tilmeld.Group },
|
|
1146
1184
|
{
|
|
1147
1185
|
type: '&',
|
|
1148
1186
|
equal: ['defaultPrimary', true],
|
|
@@ -1152,7 +1190,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1152
1190
|
generatedPrimaryGroup.parent = parent;
|
|
1153
1191
|
}
|
|
1154
1192
|
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
1155
|
-
await
|
|
1193
|
+
await tnymph.rollback(transaction);
|
|
1156
1194
|
return {
|
|
1157
1195
|
result: false,
|
|
1158
1196
|
loggedin: false,
|
|
@@ -1162,8 +1200,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
1162
1200
|
this.$data.group = generatedPrimaryGroup;
|
|
1163
1201
|
} else {
|
|
1164
1202
|
// Add the default primary.
|
|
1165
|
-
const group = await
|
|
1166
|
-
{ class: Group },
|
|
1203
|
+
const group = await tnymph.getEntity(
|
|
1204
|
+
{ class: tilmeld.Group },
|
|
1167
1205
|
{
|
|
1168
1206
|
type: '&',
|
|
1169
1207
|
equal: ['defaultPrimary', true],
|
|
@@ -1175,10 +1213,10 @@ export default class User extends AbleObject<UserData> {
|
|
|
1175
1213
|
}
|
|
1176
1214
|
|
|
1177
1215
|
// Add secondary groups.
|
|
1178
|
-
if (
|
|
1216
|
+
if (tilmeld.config.verifyEmail && tilmeld.config.unverifiedAccess) {
|
|
1179
1217
|
// Add the default secondaries for unverified users.
|
|
1180
|
-
this.$data.groups = await
|
|
1181
|
-
{ class: Group },
|
|
1218
|
+
this.$data.groups = await tnymph.getEntities(
|
|
1219
|
+
{ class: tilmeld.Group },
|
|
1182
1220
|
{
|
|
1183
1221
|
type: '&',
|
|
1184
1222
|
equal: ['unverifiedSecondary', true],
|
|
@@ -1186,8 +1224,8 @@ export default class User extends AbleObject<UserData> {
|
|
|
1186
1224
|
);
|
|
1187
1225
|
} else {
|
|
1188
1226
|
// Add the default secondaries.
|
|
1189
|
-
this.$data.groups = await
|
|
1190
|
-
{ class: Group },
|
|
1227
|
+
this.$data.groups = await tnymph.getEntities(
|
|
1228
|
+
{ class: tilmeld.Group },
|
|
1191
1229
|
{
|
|
1192
1230
|
type: '&',
|
|
1193
1231
|
equal: ['defaultSecondary', true],
|
|
@@ -1195,9 +1233,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
1195
1233
|
);
|
|
1196
1234
|
}
|
|
1197
1235
|
|
|
1198
|
-
if (
|
|
1236
|
+
if (tilmeld.config.verifyEmail) {
|
|
1199
1237
|
// The user will be enabled after verifying their e-mail address.
|
|
1200
|
-
if (!
|
|
1238
|
+
if (!tilmeld.config.unverifiedAccess) {
|
|
1201
1239
|
this.$data.enabled = false;
|
|
1202
1240
|
}
|
|
1203
1241
|
} else {
|
|
@@ -1207,9 +1245,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
1207
1245
|
// If create_admin is true and there are no other users, grant
|
|
1208
1246
|
// "system/admin".
|
|
1209
1247
|
let madeAdmin = false;
|
|
1210
|
-
if (
|
|
1211
|
-
const otherUsers = await
|
|
1212
|
-
class: User,
|
|
1248
|
+
if (tilmeld.config.createAdmin) {
|
|
1249
|
+
const otherUsers = await tnymph.getEntities({
|
|
1250
|
+
class: tilmeld.User,
|
|
1213
1251
|
skipAc: true,
|
|
1214
1252
|
limit: 1,
|
|
1215
1253
|
return: 'guid',
|
|
@@ -1224,12 +1262,13 @@ export default class User extends AbleObject<UserData> {
|
|
|
1224
1262
|
|
|
1225
1263
|
if (await this.$saveSkipAC()) {
|
|
1226
1264
|
// Send the new user registered email.
|
|
1227
|
-
if (
|
|
1228
|
-
await
|
|
1265
|
+
if (tilmeld.config.userRegisteredRecipient != null) {
|
|
1266
|
+
await tilmeld.config.sendEmail(
|
|
1267
|
+
tilmeld,
|
|
1229
1268
|
{
|
|
1230
1269
|
template: 'UserRegistered',
|
|
1231
1270
|
message: {
|
|
1232
|
-
to:
|
|
1271
|
+
to: tilmeld.config.userRegisteredRecipient,
|
|
1233
1272
|
},
|
|
1234
1273
|
locals: {
|
|
1235
1274
|
userUsername: this.$data.username,
|
|
@@ -1251,7 +1290,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1251
1290
|
if (generatedPrimaryGroup != null) {
|
|
1252
1291
|
generatedPrimaryGroup.user = this;
|
|
1253
1292
|
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
1254
|
-
await
|
|
1293
|
+
await tnymph.rollback(transaction);
|
|
1255
1294
|
return {
|
|
1256
1295
|
result: false,
|
|
1257
1296
|
loggedin: false,
|
|
@@ -1263,37 +1302,37 @@ export default class User extends AbleObject<UserData> {
|
|
|
1263
1302
|
|
|
1264
1303
|
// Finish up.
|
|
1265
1304
|
if (
|
|
1266
|
-
|
|
1267
|
-
!
|
|
1305
|
+
tilmeld.config.verifyEmail &&
|
|
1306
|
+
!tilmeld.config.unverifiedAccess &&
|
|
1268
1307
|
!madeAdmin
|
|
1269
1308
|
) {
|
|
1270
1309
|
message +=
|
|
1271
1310
|
`Almost there. An email has been sent to ${this.$data.email} ` +
|
|
1272
1311
|
'with a verification link for you to finish registration.';
|
|
1273
1312
|
} else if (
|
|
1274
|
-
|
|
1275
|
-
|
|
1313
|
+
tilmeld.config.verifyEmail &&
|
|
1314
|
+
tilmeld.config.unverifiedAccess &&
|
|
1276
1315
|
!madeAdmin
|
|
1277
1316
|
) {
|
|
1278
|
-
|
|
1317
|
+
tilmeld.login(this, true);
|
|
1279
1318
|
message +=
|
|
1280
1319
|
"You're now logged in! An email has been sent to " +
|
|
1281
1320
|
`${this.$data.email} with a verification link for you to finish ` +
|
|
1282
1321
|
'registration.';
|
|
1283
1322
|
loggedin = true;
|
|
1284
1323
|
} else {
|
|
1285
|
-
|
|
1324
|
+
tilmeld.login(this, true);
|
|
1286
1325
|
message += "You're now registered and logged in!";
|
|
1287
1326
|
loggedin = true;
|
|
1288
1327
|
}
|
|
1289
|
-
await
|
|
1328
|
+
await tnymph.commit(transaction);
|
|
1290
1329
|
return {
|
|
1291
1330
|
result: true,
|
|
1292
1331
|
loggedin,
|
|
1293
1332
|
message,
|
|
1294
1333
|
};
|
|
1295
1334
|
} else {
|
|
1296
|
-
await
|
|
1335
|
+
await tnymph.rollback(transaction);
|
|
1297
1336
|
return {
|
|
1298
1337
|
result: false,
|
|
1299
1338
|
loggedin: false,
|
|
@@ -1301,19 +1340,20 @@ export default class User extends AbleObject<UserData> {
|
|
|
1301
1340
|
};
|
|
1302
1341
|
}
|
|
1303
1342
|
} catch (e: any) {
|
|
1304
|
-
await
|
|
1343
|
+
await tnymph.rollback(transaction);
|
|
1305
1344
|
throw e;
|
|
1306
1345
|
}
|
|
1307
1346
|
}
|
|
1308
1347
|
|
|
1309
1348
|
public async $save() {
|
|
1349
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1310
1350
|
if (this.$data.username == null || !this.$data.username.trim().length) {
|
|
1311
1351
|
return false;
|
|
1312
1352
|
}
|
|
1313
1353
|
|
|
1314
1354
|
if (
|
|
1315
|
-
|
|
1316
|
-
!
|
|
1355
|
+
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
1356
|
+
!tilmeld.gatekeeper('system/admin') &&
|
|
1317
1357
|
this.$gatekeeper('system/admin')
|
|
1318
1358
|
) {
|
|
1319
1359
|
throw new BadDataError(
|
|
@@ -1325,7 +1365,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1325
1365
|
|
|
1326
1366
|
// Formatting.
|
|
1327
1367
|
this.$data.username = this.$data.username.trim();
|
|
1328
|
-
if (
|
|
1368
|
+
if (tilmeld.config.emailUsernames) {
|
|
1329
1369
|
this.$data.email = this.$data.username;
|
|
1330
1370
|
}
|
|
1331
1371
|
this.$data.nameFirst = (this.$data.nameFirst ?? '').trim();
|
|
@@ -1399,7 +1439,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1399
1439
|
if (!unCheck.result) {
|
|
1400
1440
|
throw new BadUsernameError(unCheck.message);
|
|
1401
1441
|
}
|
|
1402
|
-
if (!
|
|
1442
|
+
if (!tilmeld.config.emailUsernames) {
|
|
1403
1443
|
const emCheck = await this.$checkEmail();
|
|
1404
1444
|
if (!emCheck.result) {
|
|
1405
1445
|
throw new BadEmailError(emCheck.message);
|
|
@@ -1407,10 +1447,10 @@ export default class User extends AbleObject<UserData> {
|
|
|
1407
1447
|
}
|
|
1408
1448
|
|
|
1409
1449
|
// Email changes.
|
|
1410
|
-
if (!
|
|
1450
|
+
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1411
1451
|
// The user isn't an admin, so email address changes should contain some
|
|
1412
1452
|
// security measures.
|
|
1413
|
-
if (
|
|
1453
|
+
if (tilmeld.config.verifyEmail) {
|
|
1414
1454
|
// The user needs to verify this new email address.
|
|
1415
1455
|
if (this.guid == null) {
|
|
1416
1456
|
// If this is the first user, they'll be made an admin, so they don't
|
|
@@ -1425,16 +1465,16 @@ export default class User extends AbleObject<UserData> {
|
|
|
1425
1465
|
) {
|
|
1426
1466
|
// The user already has an old email address.
|
|
1427
1467
|
if (
|
|
1428
|
-
|
|
1468
|
+
tilmeld.config.emailRateLimit !== '' &&
|
|
1429
1469
|
this.$data.emailChangeDate != null &&
|
|
1430
1470
|
this.$data.emailChangeDate >=
|
|
1431
|
-
strtotime('-' +
|
|
1471
|
+
strtotime('-' + tilmeld.config.emailRateLimit) * 1000
|
|
1432
1472
|
) {
|
|
1433
1473
|
throw new EmailChangeRateLimitExceededError(
|
|
1434
1474
|
'You already changed your email address recently. Please wait until ' +
|
|
1435
1475
|
new Date(
|
|
1436
1476
|
strtotime(
|
|
1437
|
-
'+' +
|
|
1477
|
+
'+' + tilmeld.config.emailRateLimit,
|
|
1438
1478
|
Math.floor(this.$data.emailChangeDate / 1000)
|
|
1439
1479
|
) * 1000
|
|
1440
1480
|
).toString() +
|
|
@@ -1443,12 +1483,12 @@ export default class User extends AbleObject<UserData> {
|
|
|
1443
1483
|
} else {
|
|
1444
1484
|
if (
|
|
1445
1485
|
this.$data.newEmailSecret == null &&
|
|
1446
|
-
|
|
1486
|
+
tilmeld.config.emailRateLimit !== '' &&
|
|
1447
1487
|
// Make sure the user has at least the rate limit time to cancel
|
|
1448
1488
|
// an email change.
|
|
1449
1489
|
(this.$data.emailChangeDate == null ||
|
|
1450
1490
|
this.$data.emailChangeDate <
|
|
1451
|
-
strtotime('-' +
|
|
1491
|
+
strtotime('-' + tilmeld.config.emailRateLimit) * 1000)
|
|
1452
1492
|
) {
|
|
1453
1493
|
// Save the old email in case the cancel change link is clicked.
|
|
1454
1494
|
this.$data.cancelEmailAddress = this.$originalEmail;
|
|
@@ -1459,7 +1499,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1459
1499
|
// it).
|
|
1460
1500
|
this.$data.newEmailAddress = this.$data.email;
|
|
1461
1501
|
this.$data.email = this.$originalEmail;
|
|
1462
|
-
if (
|
|
1502
|
+
if (tilmeld.config.emailUsernames) {
|
|
1463
1503
|
this.$data.username = this.$data.email;
|
|
1464
1504
|
}
|
|
1465
1505
|
this.$data.newEmailSecret = nanoid();
|
|
@@ -1474,7 +1514,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1474
1514
|
// email change.
|
|
1475
1515
|
(this.$data.emailChangeDate == null ||
|
|
1476
1516
|
this.$data.emailChangeDate <
|
|
1477
|
-
strtotime('-' +
|
|
1517
|
+
strtotime('-' + tilmeld.config.emailRateLimit) * 1000)
|
|
1478
1518
|
) {
|
|
1479
1519
|
// The user doesn't need to verify their new email address, but should
|
|
1480
1520
|
// be able to cancel the email change from their old address.
|
|
@@ -1494,14 +1534,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
1494
1534
|
}
|
|
1495
1535
|
|
|
1496
1536
|
try {
|
|
1497
|
-
|
|
1537
|
+
tilmeld.config.validatorUser(this);
|
|
1498
1538
|
} catch (e: any) {
|
|
1499
1539
|
throw new BadDataError(e?.message);
|
|
1500
1540
|
}
|
|
1501
1541
|
|
|
1502
1542
|
// Start transaction.
|
|
1503
1543
|
const transaction = 'tilmeld-save-' + nanoid();
|
|
1504
|
-
await
|
|
1544
|
+
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1505
1545
|
|
|
1506
1546
|
if (
|
|
1507
1547
|
this.$data.group != null &&
|
|
@@ -1517,7 +1557,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1517
1557
|
this.$data.group.phone = this.$data.phone;
|
|
1518
1558
|
await this.$data.group.$saveSkipAC();
|
|
1519
1559
|
} catch (e: any) {
|
|
1520
|
-
await
|
|
1560
|
+
await tnymph.rollback(transaction);
|
|
1521
1561
|
throw e;
|
|
1522
1562
|
}
|
|
1523
1563
|
}
|
|
@@ -1530,14 +1570,14 @@ export default class User extends AbleObject<UserData> {
|
|
|
1530
1570
|
try {
|
|
1531
1571
|
ret = await super.$save();
|
|
1532
1572
|
} catch (e: any) {
|
|
1533
|
-
await
|
|
1573
|
+
await tnymph.rollback(transaction);
|
|
1534
1574
|
throw e;
|
|
1535
1575
|
}
|
|
1536
1576
|
if (ret) {
|
|
1537
1577
|
if (sendVerification) {
|
|
1538
1578
|
// The email has changed, so send a new verification email.
|
|
1539
1579
|
if (!(await this.$sendEmailVerification())) {
|
|
1540
|
-
await
|
|
1580
|
+
await tnymph.rollback(transaction);
|
|
1541
1581
|
this.guid = preGuid;
|
|
1542
1582
|
this.cdate = preCdate;
|
|
1543
1583
|
this.mdate = preMdate;
|
|
@@ -1545,16 +1585,16 @@ export default class User extends AbleObject<UserData> {
|
|
|
1545
1585
|
}
|
|
1546
1586
|
}
|
|
1547
1587
|
|
|
1548
|
-
if (User.current(true).$is(this)) {
|
|
1588
|
+
if (tilmeld.User.current(true).$is(this)) {
|
|
1549
1589
|
// Update the user in the session cache.
|
|
1550
|
-
|
|
1590
|
+
tilmeld.fillSession(this);
|
|
1551
1591
|
}
|
|
1552
1592
|
|
|
1553
1593
|
this.$descendantGroups = undefined;
|
|
1554
1594
|
this.$gatekeeperCache = undefined;
|
|
1555
|
-
await
|
|
1595
|
+
await tnymph.commit(transaction);
|
|
1556
1596
|
} else {
|
|
1557
|
-
await
|
|
1597
|
+
await tnymph.rollback(transaction);
|
|
1558
1598
|
}
|
|
1559
1599
|
return ret;
|
|
1560
1600
|
}
|
|
@@ -1576,22 +1616,21 @@ export default class User extends AbleObject<UserData> {
|
|
|
1576
1616
|
}
|
|
1577
1617
|
|
|
1578
1618
|
public async $delete() {
|
|
1579
|
-
|
|
1619
|
+
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1620
|
+
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1580
1621
|
throw new BadDataError("You don't have the authority to delete users.");
|
|
1581
1622
|
}
|
|
1582
1623
|
if (
|
|
1583
|
-
!
|
|
1624
|
+
!tilmeld.gatekeeper('system/admin') &&
|
|
1584
1625
|
this.$gatekeeper('system/admin')
|
|
1585
1626
|
) {
|
|
1586
1627
|
throw new BadDataError(
|
|
1587
1628
|
"You don't have the authority to delete system admins."
|
|
1588
1629
|
);
|
|
1589
1630
|
}
|
|
1590
|
-
if (User.current(true).$is(this)) {
|
|
1631
|
+
if (tilmeld.User.current(true).$is(this)) {
|
|
1591
1632
|
this.$logout();
|
|
1592
1633
|
}
|
|
1593
1634
|
return await super.$delete();
|
|
1594
1635
|
}
|
|
1595
1636
|
}
|
|
1596
|
-
|
|
1597
|
-
Nymph.setEntityClass(User.class, User);
|