@nymphjs/tilmeld 1.0.0-beta.17 → 1.0.0-beta.19
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 +19 -0
- package/README.md +13 -0
- package/dist/Group.js +48 -22
- package/dist/Group.js.map +1 -1
- package/dist/Tilmeld.d.ts +3 -0
- package/dist/Tilmeld.js +99 -29
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +8 -0
- package/dist/User.js +129 -42
- package/dist/User.js.map +1 -1
- package/dist/conf/d.d.ts +2 -1
- package/dist/conf/defaults.js +3 -2
- package/dist/conf/defaults.js.map +1 -1
- package/dist/enforceTilmeld.d.ts +3 -0
- package/dist/enforceTilmeld.js +22 -0
- package/dist/enforceTilmeld.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/Group.ts +70 -23
- package/src/Tilmeld.ts +139 -42
- package/src/User.ts +193 -43
- package/src/conf/d.ts +10 -1
- package/src/conf/defaults.ts +3 -2
- package/src/enforceTilmeld.ts +20 -0
- package/src/index.ts +2 -0
package/src/User.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { difference } from 'lodash';
|
|
|
14
14
|
import { humanSecret, nanoid } from '@nymphjs/guid';
|
|
15
15
|
|
|
16
16
|
import type Tilmeld from './Tilmeld';
|
|
17
|
+
import { enforceTilmeld } from './enforceTilmeld';
|
|
17
18
|
import AbleObject from './AbleObject';
|
|
18
19
|
import Group, { GroupData } from './Group';
|
|
19
20
|
import {
|
|
@@ -145,7 +146,8 @@ export type UserData = {
|
|
|
145
146
|
*/
|
|
146
147
|
newEmailSecret?: string;
|
|
147
148
|
/**
|
|
148
|
-
*
|
|
149
|
+
* If the user has changed their email address, this is the new one, awaiting
|
|
150
|
+
* verification.
|
|
149
151
|
*/
|
|
150
152
|
newEmailAddress?: string;
|
|
151
153
|
/**
|
|
@@ -211,23 +213,31 @@ export default class User extends AbleObject<UserData> {
|
|
|
211
213
|
'$register',
|
|
212
214
|
];
|
|
213
215
|
private static DEFAULT_PRIVATE_DATA = [
|
|
216
|
+
// The things that are commented are there to show what is _not_ private.
|
|
217
|
+
'abilities',
|
|
218
|
+
// 'username',
|
|
219
|
+
// 'nameFirst',
|
|
220
|
+
// 'nameMiddle',
|
|
221
|
+
// 'nameLast',
|
|
222
|
+
// 'name',
|
|
214
223
|
'email',
|
|
215
|
-
'
|
|
224
|
+
// 'avatar',
|
|
216
225
|
'phone',
|
|
217
226
|
'group',
|
|
218
227
|
'groups',
|
|
219
|
-
'abilities',
|
|
220
228
|
'inheritAbilities',
|
|
221
|
-
'
|
|
222
|
-
'recoverSecretDate',
|
|
223
|
-
'password',
|
|
224
|
-
'salt',
|
|
229
|
+
'enabled',
|
|
225
230
|
'secret',
|
|
226
|
-
'
|
|
231
|
+
'emailChangeDate',
|
|
227
232
|
'newEmailSecret',
|
|
228
|
-
'
|
|
233
|
+
'newEmailAddress',
|
|
229
234
|
'cancelEmailSecret',
|
|
230
|
-
'
|
|
235
|
+
'cancelEmailAddress',
|
|
236
|
+
'recoverSecret',
|
|
237
|
+
'recoverSecretDate',
|
|
238
|
+
'salt',
|
|
239
|
+
'password',
|
|
240
|
+
'passwordTemp',
|
|
231
241
|
];
|
|
232
242
|
private static DEFAULT_ALLOWLIST_DATA: string[] = [];
|
|
233
243
|
|
|
@@ -512,7 +522,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
512
522
|
password: string;
|
|
513
523
|
additionalData?: { [k: string]: any };
|
|
514
524
|
}) {
|
|
515
|
-
const tilmeld = this
|
|
525
|
+
const tilmeld = enforceTilmeld(this);
|
|
516
526
|
if (this.guid == null) {
|
|
517
527
|
return { result: false, message: 'Incorrect login/password.' };
|
|
518
528
|
}
|
|
@@ -556,12 +566,84 @@ export default class User extends AbleObject<UserData> {
|
|
|
556
566
|
return { result: true, message: 'You are logged in.' };
|
|
557
567
|
}
|
|
558
568
|
|
|
569
|
+
public async $switchUser(data?: { additionalData?: { [k: string]: any } }) {
|
|
570
|
+
const tilmeld = enforceTilmeld(this);
|
|
571
|
+
if (this.guid == null) {
|
|
572
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
let user = tilmeld.User.current();
|
|
576
|
+
|
|
577
|
+
if (!user || user.guid == null) {
|
|
578
|
+
return { result: false, message: "You're not logged in." };
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const isCurrentUser = user != null && user.$is(this);
|
|
582
|
+
|
|
583
|
+
if (isCurrentUser) {
|
|
584
|
+
return { result: false, message: "You can't switch to yourself." };
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const toAbilities = this.$data.abilities || [];
|
|
588
|
+
const fromAbilities = user.abilities || [];
|
|
589
|
+
|
|
590
|
+
if (
|
|
591
|
+
fromAbilities.indexOf('tilmeld/switch') === -1 &&
|
|
592
|
+
fromAbilities.indexOf('system/admin') === -1
|
|
593
|
+
) {
|
|
594
|
+
return {
|
|
595
|
+
result: false,
|
|
596
|
+
message: "You don't have permission to switch users.",
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (
|
|
601
|
+
toAbilities.indexOf('system/admin') !== -1 ||
|
|
602
|
+
toAbilities.indexOf('tilmeld/admin') !== -1
|
|
603
|
+
) {
|
|
604
|
+
return { result: false, message: "You can't switch to an admin." };
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
try {
|
|
608
|
+
for (let callback of (this.constructor as typeof User)
|
|
609
|
+
.beforeLoginCallbacks) {
|
|
610
|
+
if (callback) {
|
|
611
|
+
await callback(this, {
|
|
612
|
+
username: this.$data.username || '',
|
|
613
|
+
password: '',
|
|
614
|
+
...(data || {}),
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
} catch (e: any) {
|
|
619
|
+
return {
|
|
620
|
+
result: false,
|
|
621
|
+
message: e.message,
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// Authentication was successful, attempt to login.
|
|
626
|
+
if (!tilmeld.loginSwitch(this, true)) {
|
|
627
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
for (let callback of (this.constructor as typeof User)
|
|
631
|
+
.afterLoginCallbacks) {
|
|
632
|
+
if (callback) {
|
|
633
|
+
await callback(this);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Login was successful.
|
|
638
|
+
return { result: true, message: 'You are logged in.' };
|
|
639
|
+
}
|
|
640
|
+
|
|
559
641
|
/**
|
|
560
642
|
* Log a user out of the system.
|
|
561
643
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
562
644
|
*/
|
|
563
645
|
public async $logout() {
|
|
564
|
-
const tilmeld = this
|
|
646
|
+
const tilmeld = enforceTilmeld(this);
|
|
565
647
|
|
|
566
648
|
try {
|
|
567
649
|
for (let callback of (this.constructor as typeof User)
|
|
@@ -640,18 +722,39 @@ export default class User extends AbleObject<UserData> {
|
|
|
640
722
|
}
|
|
641
723
|
|
|
642
724
|
public $jsonAcceptData(input: EntityJson, allowConflict = false) {
|
|
643
|
-
const tilmeld = this
|
|
725
|
+
const tilmeld = enforceTilmeld(this);
|
|
644
726
|
this.$referenceWake();
|
|
645
727
|
|
|
646
728
|
if (
|
|
647
729
|
'abilities' in input.data &&
|
|
648
|
-
input.data.abilities
|
|
649
|
-
|
|
650
|
-
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
730
|
+
input.data.abilities?.includes('system/admin') !==
|
|
731
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
651
732
|
!tilmeld.gatekeeper('system/admin')
|
|
652
733
|
) {
|
|
653
734
|
throw new BadDataError(
|
|
654
|
-
"You don't have the authority to
|
|
735
|
+
"You don't have the authority to grant or revoke system/admin."
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (
|
|
740
|
+
'abilities' in input.data &&
|
|
741
|
+
input.data.abilities?.includes('tilmeld/admin') !==
|
|
742
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
743
|
+
!tilmeld.gatekeeper('system/admin')
|
|
744
|
+
) {
|
|
745
|
+
throw new BadDataError(
|
|
746
|
+
"You don't have the authority to grant or revoke tilmeld/admin."
|
|
747
|
+
);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
if (
|
|
751
|
+
'abilities' in input.data &&
|
|
752
|
+
input.data.abilities?.includes('tilmeld/switch') !==
|
|
753
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
754
|
+
!tilmeld.gatekeeper('system/admin')
|
|
755
|
+
) {
|
|
756
|
+
throw new BadDataError(
|
|
757
|
+
"You don't have the authority to grant or revoke tilmeld/switch."
|
|
655
758
|
);
|
|
656
759
|
}
|
|
657
760
|
|
|
@@ -660,18 +763,39 @@ export default class User extends AbleObject<UserData> {
|
|
|
660
763
|
}
|
|
661
764
|
|
|
662
765
|
public $jsonAcceptPatch(patch: EntityPatch, allowConflict = false) {
|
|
663
|
-
const tilmeld = this
|
|
766
|
+
const tilmeld = enforceTilmeld(this);
|
|
664
767
|
this.$referenceWake();
|
|
665
768
|
|
|
666
769
|
if (
|
|
667
770
|
'abilities' in patch.set &&
|
|
668
|
-
patch.set.abilities
|
|
669
|
-
|
|
670
|
-
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
771
|
+
patch.set.abilities?.includes('system/admin') !==
|
|
772
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
671
773
|
!tilmeld.gatekeeper('system/admin')
|
|
672
774
|
) {
|
|
673
775
|
throw new BadDataError(
|
|
674
|
-
"You don't have the authority to
|
|
776
|
+
"You don't have the authority to grant or revoke system/admin."
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
if (
|
|
781
|
+
'abilities' in patch.set &&
|
|
782
|
+
patch.set.abilities?.includes('tilmeld/admin') !==
|
|
783
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
784
|
+
!tilmeld.gatekeeper('system/admin')
|
|
785
|
+
) {
|
|
786
|
+
throw new BadDataError(
|
|
787
|
+
"You don't have the authority to grant or revoke tilmeld/admin."
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (
|
|
792
|
+
'abilities' in patch.set &&
|
|
793
|
+
patch.set.abilities?.includes('tilmeld/switch') !==
|
|
794
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
795
|
+
!tilmeld.gatekeeper('system/admin')
|
|
796
|
+
) {
|
|
797
|
+
throw new BadDataError(
|
|
798
|
+
"You don't have the authority to grant or revoke tilmeld/switch."
|
|
675
799
|
);
|
|
676
800
|
}
|
|
677
801
|
|
|
@@ -690,7 +814,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
690
814
|
* @param givenUser User to update protection for. If undefined, will use the currently logged in user.
|
|
691
815
|
*/
|
|
692
816
|
public $updateDataProtection(givenUser?: User & UserData) {
|
|
693
|
-
const tilmeld = this
|
|
817
|
+
const tilmeld = enforceTilmeld(this);
|
|
694
818
|
let user = givenUser ?? tilmeld.User.current();
|
|
695
819
|
|
|
696
820
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
@@ -745,17 +869,43 @@ export default class User extends AbleObject<UserData> {
|
|
|
745
869
|
this.$allowlistData.push('phone');
|
|
746
870
|
}
|
|
747
871
|
this.$privateData = [
|
|
872
|
+
// The things that are commented are there to show what is _not_ private.
|
|
873
|
+
// 'abilities',
|
|
874
|
+
// 'username',
|
|
875
|
+
// 'nameFirst',
|
|
876
|
+
// 'nameMiddle',
|
|
877
|
+
// 'nameLast',
|
|
878
|
+
// 'name',
|
|
879
|
+
// 'email',
|
|
880
|
+
// 'avatar',
|
|
881
|
+
// 'phone',
|
|
882
|
+
// 'group',
|
|
883
|
+
// 'groups',
|
|
884
|
+
// 'inheritAbilities',
|
|
885
|
+
'enabled',
|
|
748
886
|
'secret',
|
|
887
|
+
'emailChangeDate',
|
|
749
888
|
'newEmailSecret',
|
|
750
|
-
'
|
|
889
|
+
// 'newEmailAddress',
|
|
751
890
|
'cancelEmailSecret',
|
|
752
|
-
'
|
|
891
|
+
'cancelEmailAddress',
|
|
753
892
|
'recoverSecret',
|
|
754
893
|
'recoverSecretDate',
|
|
755
|
-
'password',
|
|
756
894
|
'salt',
|
|
895
|
+
'password',
|
|
896
|
+
'passwordTemp',
|
|
757
897
|
];
|
|
758
898
|
}
|
|
899
|
+
|
|
900
|
+
if (
|
|
901
|
+
user != null &&
|
|
902
|
+
!isCurrentUser &&
|
|
903
|
+
(abilities.indexOf('tilmeld/switch') !== -1 ||
|
|
904
|
+
abilities.indexOf('system/admin') !== -1)
|
|
905
|
+
) {
|
|
906
|
+
// Users with this ability can switch to other users.
|
|
907
|
+
this.$clientEnabledMethods.push('$switchUser');
|
|
908
|
+
}
|
|
759
909
|
}
|
|
760
910
|
|
|
761
911
|
/**
|
|
@@ -773,7 +923,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
773
923
|
* @returns True or false.
|
|
774
924
|
*/
|
|
775
925
|
public $gatekeeper(ability?: string): boolean {
|
|
776
|
-
const tilmeld = this
|
|
926
|
+
const tilmeld = enforceTilmeld(this);
|
|
777
927
|
if (ability == null) {
|
|
778
928
|
return tilmeld.User.current()?.$is(this) ?? false;
|
|
779
929
|
}
|
|
@@ -800,7 +950,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
800
950
|
}
|
|
801
951
|
return (
|
|
802
952
|
(ability in this.$gatekeeperCache && !!this.$gatekeeperCache[ability]) ||
|
|
803
|
-
!!this.$
|
|
953
|
+
!!this.$data.abilities?.includes('system/admin')
|
|
804
954
|
);
|
|
805
955
|
}
|
|
806
956
|
|
|
@@ -817,7 +967,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
817
967
|
* @returns True on success, false on failure.
|
|
818
968
|
*/
|
|
819
969
|
public async $sendEmailVerification() {
|
|
820
|
-
const tilmeld = this
|
|
970
|
+
const tilmeld = enforceTilmeld(this);
|
|
821
971
|
if (this.guid == null) {
|
|
822
972
|
return false;
|
|
823
973
|
}
|
|
@@ -930,7 +1080,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
930
1080
|
* @returns True if the passwords match, otherwise false.
|
|
931
1081
|
*/
|
|
932
1082
|
public $checkPassword(password: string) {
|
|
933
|
-
const tilmeld = this
|
|
1083
|
+
const tilmeld = enforceTilmeld(this);
|
|
934
1084
|
switch (tilmeld.config.pwMethod) {
|
|
935
1085
|
case 'plain':
|
|
936
1086
|
return this.$data.password === password;
|
|
@@ -1041,7 +1191,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1041
1191
|
* @returns The resulting password or hash which is stored in the entity.
|
|
1042
1192
|
*/
|
|
1043
1193
|
public $password(password: string) {
|
|
1044
|
-
const tilmeld = this
|
|
1194
|
+
const tilmeld = enforceTilmeld(this);
|
|
1045
1195
|
switch (tilmeld.config.pwMethod) {
|
|
1046
1196
|
case 'plain':
|
|
1047
1197
|
delete this.$data.salt;
|
|
@@ -1068,7 +1218,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1068
1218
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
1069
1219
|
*/
|
|
1070
1220
|
public async $checkUsername(): Promise<{ result: boolean; message: string }> {
|
|
1071
|
-
const tilmeld = this
|
|
1221
|
+
const tilmeld = enforceTilmeld(this);
|
|
1072
1222
|
if (!tilmeld.config.emailUsernames) {
|
|
1073
1223
|
if (this.$data.username == null || !this.$data.username.length) {
|
|
1074
1224
|
return { result: false, message: 'Please specify a username.' };
|
|
@@ -1167,7 +1317,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1167
1317
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
1168
1318
|
*/
|
|
1169
1319
|
public async $checkEmail(): Promise<{ result: boolean; message: string }> {
|
|
1170
|
-
const tilmeld = this
|
|
1320
|
+
const tilmeld = enforceTilmeld(this);
|
|
1171
1321
|
if (this.$data.email == null || !this.$data.email.length) {
|
|
1172
1322
|
if (tilmeld.config.verifyEmail) {
|
|
1173
1323
|
return { result: false, message: 'Please specify an email.' };
|
|
@@ -1212,7 +1362,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1212
1362
|
* @returns An object with a boolean 'result' entry and a 'message' entry.
|
|
1213
1363
|
*/
|
|
1214
1364
|
public async $checkPhone(): Promise<{ result: boolean; message: string }> {
|
|
1215
|
-
const tilmeld = this
|
|
1365
|
+
const tilmeld = enforceTilmeld(this);
|
|
1216
1366
|
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
1217
1367
|
return { result: false, message: 'Please specify a phone number.' };
|
|
1218
1368
|
}
|
|
@@ -1251,7 +1401,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1251
1401
|
password: string;
|
|
1252
1402
|
additionalData?: { [k: string]: any };
|
|
1253
1403
|
}): Promise<{ result: boolean; loggedin: boolean; message: string }> {
|
|
1254
|
-
let tilmeld = this
|
|
1404
|
+
let tilmeld = enforceTilmeld(this);
|
|
1255
1405
|
if (!tilmeld.config.allowRegistration) {
|
|
1256
1406
|
return {
|
|
1257
1407
|
result: false,
|
|
@@ -1313,7 +1463,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1313
1463
|
const nymph = this.$nymph;
|
|
1314
1464
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1315
1465
|
this.$nymph = tnymph;
|
|
1316
|
-
tilmeld = this
|
|
1466
|
+
tilmeld = enforceTilmeld(this);
|
|
1317
1467
|
|
|
1318
1468
|
try {
|
|
1319
1469
|
// Add primary group.
|
|
@@ -1518,7 +1668,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1518
1668
|
}
|
|
1519
1669
|
|
|
1520
1670
|
public async $save() {
|
|
1521
|
-
let tilmeld = this
|
|
1671
|
+
let tilmeld = enforceTilmeld(this);
|
|
1522
1672
|
if (this.$data.username == null || !this.$data.username.trim().length) {
|
|
1523
1673
|
return false;
|
|
1524
1674
|
}
|
|
@@ -1526,7 +1676,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1526
1676
|
if (
|
|
1527
1677
|
tilmeld.gatekeeper('tilmeld/admin') &&
|
|
1528
1678
|
!tilmeld.gatekeeper('system/admin') &&
|
|
1529
|
-
this.$
|
|
1679
|
+
this.$data.abilities?.includes('system/admin')
|
|
1530
1680
|
) {
|
|
1531
1681
|
throw new BadDataError(
|
|
1532
1682
|
"You don't have the authority to modify system admins."
|
|
@@ -1716,7 +1866,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1716
1866
|
const nymph = this.$nymph;
|
|
1717
1867
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1718
1868
|
this.$nymph = tnymph;
|
|
1719
|
-
tilmeld = this
|
|
1869
|
+
tilmeld = enforceTilmeld(this);
|
|
1720
1870
|
|
|
1721
1871
|
if (
|
|
1722
1872
|
this.$data.group != null &&
|
|
@@ -1767,9 +1917,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
1767
1917
|
this.$gatekeeperCache = undefined;
|
|
1768
1918
|
await tnymph.commit(transaction);
|
|
1769
1919
|
|
|
1770
|
-
if ((nymph
|
|
1920
|
+
if (enforceTilmeld(nymph).User.current(true).$is(this)) {
|
|
1771
1921
|
// Update the user in the session cache.
|
|
1772
|
-
(nymph
|
|
1922
|
+
enforceTilmeld(nymph).fillSession(this);
|
|
1773
1923
|
}
|
|
1774
1924
|
} else {
|
|
1775
1925
|
await tnymph.rollback(transaction);
|
|
@@ -1795,13 +1945,13 @@ export default class User extends AbleObject<UserData> {
|
|
|
1795
1945
|
}
|
|
1796
1946
|
|
|
1797
1947
|
public async $delete() {
|
|
1798
|
-
const tilmeld = this
|
|
1948
|
+
const tilmeld = enforceTilmeld(this);
|
|
1799
1949
|
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1800
1950
|
throw new BadDataError("You don't have the authority to delete users.");
|
|
1801
1951
|
}
|
|
1802
1952
|
if (
|
|
1803
1953
|
!tilmeld.gatekeeper('system/admin') &&
|
|
1804
|
-
this.$
|
|
1954
|
+
this.$data.abilities?.includes('system/admin')
|
|
1805
1955
|
) {
|
|
1806
1956
|
throw new BadDataError(
|
|
1807
1957
|
"You don't have the authority to delete system admins."
|
package/src/conf/d.ts
CHANGED
|
@@ -217,6 +217,11 @@ export interface Config {
|
|
|
217
217
|
* How long from current time, in seconds, the JWT token expires.
|
|
218
218
|
*/
|
|
219
219
|
jwtExpire: number;
|
|
220
|
+
/**
|
|
221
|
+
* How long from current time, in seconds, the JWT token for a user switch
|
|
222
|
+
* expires.
|
|
223
|
+
*/
|
|
224
|
+
jwtSwitchExpire: number;
|
|
220
225
|
/**
|
|
221
226
|
* How long, in seconds, before the JWT token expires to give the user a new
|
|
222
227
|
* one.
|
|
@@ -225,7 +230,11 @@ export interface Config {
|
|
|
225
230
|
/**
|
|
226
231
|
* Function to build the JWT for user sessions.
|
|
227
232
|
*/
|
|
228
|
-
jwtBuilder: (
|
|
233
|
+
jwtBuilder: (
|
|
234
|
+
config: Config,
|
|
235
|
+
user: User & UserData,
|
|
236
|
+
switchToken?: boolean
|
|
237
|
+
) => string;
|
|
229
238
|
/**
|
|
230
239
|
* Function to verify that a JWT was signed with the secret key, vaildate its
|
|
231
240
|
* data, validate the XSRF token, and extract the GUID.
|
package/src/conf/defaults.ts
CHANGED
|
@@ -52,8 +52,9 @@ export default {
|
|
|
52
52
|
maxUsernameLength: 128,
|
|
53
53
|
jwtSecret: '',
|
|
54
54
|
jwtExpire: 60 * 60 * 24 * 7 * 8, // 8 weeks(ish)
|
|
55
|
+
jwtSwitchExpire: 60 * 60 * 6, // 6 hours
|
|
55
56
|
jwtRenew: 60 * 60 * 24 * 7 * 2, // 2 weeks(ish)
|
|
56
|
-
jwtBuilder: (config, user) => {
|
|
57
|
+
jwtBuilder: (config, user, switchToken) => {
|
|
57
58
|
const secret = config.jwtSecret;
|
|
58
59
|
if (secret === '') {
|
|
59
60
|
throw new Error('JWT secret is not configured.');
|
|
@@ -67,7 +68,7 @@ export default {
|
|
|
67
68
|
xsrfToken: 'TILMELDXSRF-' + nanoid(),
|
|
68
69
|
},
|
|
69
70
|
secret,
|
|
70
|
-
{ expiresIn: config.jwtExpire }
|
|
71
|
+
{ expiresIn: switchToken ? config.jwtSwitchExpire : config.jwtExpire }
|
|
71
72
|
);
|
|
72
73
|
},
|
|
73
74
|
jwtExtract: (config, token, xsrfToken?) => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Entity, EntityConstructor, Nymph } from '@nymphjs/nymph';
|
|
2
|
+
|
|
3
|
+
import Tilmeld from './Tilmeld';
|
|
4
|
+
|
|
5
|
+
export function enforceTilmeld(object: Nymph | Entity | EntityConstructor) {
|
|
6
|
+
let tilmeld: Tilmeld | undefined;
|
|
7
|
+
if (object instanceof Entity) {
|
|
8
|
+
tilmeld = object.$nymph.tilmeld as Tilmeld | undefined;
|
|
9
|
+
} else if (object instanceof Nymph) {
|
|
10
|
+
tilmeld = object.tilmeld as Tilmeld | undefined;
|
|
11
|
+
} else {
|
|
12
|
+
tilmeld = object.nymph.tilmeld as Tilmeld | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (tilmeld == null) {
|
|
16
|
+
throw new Error('Tilmeld was not configured on this Nymph instance!');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return tilmeld;
|
|
20
|
+
}
|