@nymphjs/tilmeld 1.0.0-beta.40 → 1.0.0-beta.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/src/User.ts CHANGED
@@ -312,21 +312,19 @@ export default class User extends AbleObject<UserData> {
312
312
  return entity;
313
313
  }
314
314
 
315
- static factorySync(guid?: string): User & UserData {
316
- return super.factorySync(guid) as User & UserData;
315
+ static factorySync(): User & UserData {
316
+ return super.factorySync() as User & UserData;
317
317
  }
318
318
 
319
- constructor(guid?: string) {
320
- super(guid);
319
+ constructor() {
320
+ super();
321
321
 
322
- if (this.guid == null) {
323
- // Defaults.
324
- this.$data.enabled = true;
325
- this.$data.abilities = [];
326
- this.$data.groups = [];
327
- this.$data.inheritAbilities = true;
328
- this.$updateDataProtection();
329
- }
322
+ // Defaults.
323
+ this.$data.enabled = true;
324
+ this.$data.abilities = [];
325
+ this.$data.groups = [];
326
+ this.$data.inheritAbilities = true;
327
+ this.$updateDataProtection();
330
328
  }
331
329
 
332
330
  public static current(returnObjectIfNotExist: true): User & UserData;
@@ -544,7 +542,7 @@ export default class User extends AbleObject<UserData> {
544
542
  if (!this.$data.enabled) {
545
543
  return { result: false, message: 'This user is disabled.' };
546
544
  }
547
- if (this.$gatekeeper()) {
545
+ if (await this.$gatekeeper()) {
548
546
  return { result: true, message: 'You are already logged in.' };
549
547
  }
550
548
  if (!this.$checkPassword(data.password)) {
@@ -584,7 +582,7 @@ export default class User extends AbleObject<UserData> {
584
582
  }
585
583
 
586
584
  // Authentication was successful, attempt to login.
587
- if (!tilmeld.login(this, true)) {
585
+ if (!(await tilmeld.login(this, true))) {
588
586
  return { result: false, message: 'Incorrect login/password.' };
589
587
  }
590
588
 
@@ -656,7 +654,7 @@ export default class User extends AbleObject<UserData> {
656
654
  }
657
655
 
658
656
  // Authentication was successful, attempt to login.
659
- if (!tilmeld.loginSwitch(this, true)) {
657
+ if (!(await tilmeld.loginSwitch(this, true))) {
660
658
  return { result: false, message: 'Incorrect login/password.' };
661
659
  }
662
660
 
@@ -692,7 +690,7 @@ export default class User extends AbleObject<UserData> {
692
690
  };
693
691
  }
694
692
 
695
- tilmeld.logout();
693
+ await tilmeld.logout();
696
694
 
697
695
  for (let callback of (this.constructor as typeof User)
698
696
  .afterLogoutCallbacks) {
@@ -718,36 +716,36 @@ export default class User extends AbleObject<UserData> {
718
716
  );
719
717
  }
720
718
 
721
- /**
722
- * Get the user's group descendants.
723
- */
724
- public async $getDescendantGroups(): Promise<(Group & GroupData)[]> {
725
- if (this.$descendantGroups == null) {
726
- this.$descendantGroups = [];
727
- if (this.$data.group != null) {
728
- this.$descendantGroups = await this.$data.group.$getDescendants();
729
- }
730
- for (let curGroup of this.$data.groups ?? []) {
731
- this.$descendantGroups = this.$descendantGroups?.concat(
732
- await curGroup.$getDescendants()
733
- );
734
- }
719
+ public $getGid() {
720
+ if (this.$data.group) {
721
+ return this.$data.group.guid;
735
722
  }
736
- return this.$descendantGroups;
723
+ return null;
724
+ }
725
+
726
+ public $getGids() {
727
+ if (this.$data.groups) {
728
+ return this.$data.groups
729
+ .map((group) => group.guid)
730
+ .filter((guid) => guid != null) as string[];
731
+ }
732
+ return null;
737
733
  }
738
734
 
739
735
  /**
740
736
  * Get the user's group descendants.
741
737
  */
742
- public $getDescendantGroupsSync(): (Group & GroupData)[] {
738
+ public async $getDescendantGroups(): Promise<(Group & GroupData)[]> {
743
739
  if (this.$descendantGroups == null) {
744
740
  this.$descendantGroups = [];
745
741
  if (this.$data.group != null) {
746
- this.$descendantGroups = this.$data.group.$getDescendantsSync();
742
+ await this.$data.group.$wake();
743
+ this.$descendantGroups = await this.$data.group.$getDescendants();
747
744
  }
745
+ await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
748
746
  for (let curGroup of this.$data.groups ?? []) {
749
747
  this.$descendantGroups = this.$descendantGroups?.concat(
750
- curGroup.$getDescendantsSync()
748
+ await curGroup.$getDescendants()
751
749
  );
752
750
  }
753
751
  }
@@ -756,13 +754,14 @@ export default class User extends AbleObject<UserData> {
756
754
 
757
755
  public $jsonAcceptData(input: EntityJson, allowConflict = false) {
758
756
  const tilmeld = enforceTilmeld(this);
759
- this.$referenceWake();
757
+ this.$check();
760
758
 
761
759
  if (
762
760
  'abilities' in input.data &&
763
761
  input.data.abilities?.includes('system/admin') !==
764
762
  this.$data.abilities?.includes('system/admin') &&
765
- !tilmeld.gatekeeper('system/admin')
763
+ (!tilmeld.currentUser ||
764
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
766
765
  ) {
767
766
  throw new BadDataError(
768
767
  "You don't have the authority to grant or revoke system/admin."
@@ -773,7 +772,8 @@ export default class User extends AbleObject<UserData> {
773
772
  'abilities' in input.data &&
774
773
  input.data.abilities?.includes('tilmeld/admin') !==
775
774
  this.$data.abilities?.includes('tilmeld/admin') &&
776
- !tilmeld.gatekeeper('system/admin')
775
+ (!tilmeld.currentUser ||
776
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
777
777
  ) {
778
778
  throw new BadDataError(
779
779
  "You don't have the authority to grant or revoke tilmeld/admin."
@@ -784,7 +784,8 @@ export default class User extends AbleObject<UserData> {
784
784
  'abilities' in input.data &&
785
785
  input.data.abilities?.includes('tilmeld/switch') !==
786
786
  this.$data.abilities?.includes('tilmeld/switch') &&
787
- !tilmeld.gatekeeper('system/admin')
787
+ (!tilmeld.currentUser ||
788
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
788
789
  ) {
789
790
  throw new BadDataError(
790
791
  "You don't have the authority to grant or revoke tilmeld/switch."
@@ -797,13 +798,14 @@ export default class User extends AbleObject<UserData> {
797
798
 
798
799
  public $jsonAcceptPatch(patch: EntityPatch, allowConflict = false) {
799
800
  const tilmeld = enforceTilmeld(this);
800
- this.$referenceWake();
801
+ this.$check();
801
802
 
802
803
  if (
803
804
  'abilities' in patch.set &&
804
805
  patch.set.abilities?.includes('system/admin') !==
805
806
  this.$data.abilities?.includes('system/admin') &&
806
- !tilmeld.gatekeeper('system/admin')
807
+ (!tilmeld.currentUser ||
808
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
807
809
  ) {
808
810
  throw new BadDataError(
809
811
  "You don't have the authority to grant or revoke system/admin."
@@ -814,7 +816,8 @@ export default class User extends AbleObject<UserData> {
814
816
  'abilities' in patch.set &&
815
817
  patch.set.abilities?.includes('tilmeld/admin') !==
816
818
  this.$data.abilities?.includes('tilmeld/admin') &&
817
- !tilmeld.gatekeeper('system/admin')
819
+ (!tilmeld.currentUser ||
820
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
818
821
  ) {
819
822
  throw new BadDataError(
820
823
  "You don't have the authority to grant or revoke tilmeld/admin."
@@ -825,7 +828,8 @@ export default class User extends AbleObject<UserData> {
825
828
  'abilities' in patch.set &&
826
829
  patch.set.abilities?.includes('tilmeld/switch') !==
827
830
  this.$data.abilities?.includes('tilmeld/switch') &&
828
- !tilmeld.gatekeeper('system/admin')
831
+ (!tilmeld.currentUser ||
832
+ !tilmeld.currentUser.abilities?.includes('system/admin'))
829
833
  ) {
830
834
  throw new BadDataError(
831
835
  "You don't have the authority to grant or revoke tilmeld/switch."
@@ -948,6 +952,17 @@ export default class User extends AbleObject<UserData> {
948
952
  }
949
953
  }
950
954
 
955
+ public $updateGroupDataProtection() {
956
+ if (this.$data.group != null && !this.$data.group.$asleep()) {
957
+ this.$data.group.$updateDataProtection();
958
+ }
959
+ for (let group of this.$data.groups ?? []) {
960
+ if (!group.$asleep()) {
961
+ group.$updateDataProtection();
962
+ }
963
+ }
964
+ }
965
+
951
966
  /**
952
967
  * Check to see if a user has an ability.
953
968
  *
@@ -962,31 +977,14 @@ export default class User extends AbleObject<UserData> {
962
977
  * @param ability The ability.
963
978
  * @returns True or false.
964
979
  */
965
- public $gatekeeper(ability?: string): boolean {
980
+ public async $gatekeeper(ability?: string): Promise<boolean> {
966
981
  const tilmeld = enforceTilmeld(this);
967
982
  if (ability == null) {
968
983
  return tilmeld.User.current()?.$is(this) ?? false;
969
984
  }
970
985
  // Check the cache to see if we've already checked this user.
971
986
  if (this.$gatekeeperCache == null) {
972
- let abilities = this.$data.abilities ?? [];
973
- if (this.$data.inheritAbilities) {
974
- for (let curGroup of this.$data.groups ?? []) {
975
- if (curGroup.enabled) {
976
- abilities = abilities.concat(curGroup.abilities ?? []);
977
- }
978
- }
979
- if (
980
- this.$data.group != null &&
981
- this.$data.group.cdate != null &&
982
- this.$data.group.enabled
983
- ) {
984
- abilities = abilities.concat(this.$data.group.abilities ?? []);
985
- }
986
- }
987
- this.$gatekeeperCache = Object.fromEntries(
988
- abilities.map((ability) => [ability, true])
989
- );
987
+ this.$gatekeeperCache = await this.$getGatekeeperCache();
990
988
  }
991
989
  return (
992
990
  (ability in this.$gatekeeperCache && !!this.$gatekeeperCache[ability]) ||
@@ -994,6 +992,29 @@ export default class User extends AbleObject<UserData> {
994
992
  );
995
993
  }
996
994
 
995
+ /**
996
+ * Build a gatekeeper cache object.
997
+ */
998
+ public async $getGatekeeperCache() {
999
+ let abilities = this.$data.abilities ?? [];
1000
+ if (this.$data.inheritAbilities) {
1001
+ await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
1002
+ for (let curGroup of this.$data.groups ?? []) {
1003
+ if (curGroup.enabled) {
1004
+ abilities = abilities.concat(curGroup.abilities ?? []);
1005
+ }
1006
+ }
1007
+ await this.$data.group?.$wake();
1008
+ const group = this.$data.group;
1009
+ if (group != null && group.cdate != null && group.enabled) {
1010
+ abilities = abilities.concat(group.abilities ?? []);
1011
+ }
1012
+ }
1013
+ return Object.fromEntries(
1014
+ abilities.map((ability) => [ability, true as true])
1015
+ );
1016
+ }
1017
+
997
1018
  public $clearCache() {
998
1019
  const ret = super.$clearCache();
999
1020
  this.$descendantGroups = undefined;
@@ -1102,13 +1123,16 @@ export default class User extends AbleObject<UserData> {
1102
1123
  * @param group The group.
1103
1124
  * @returns True if the user is already in the group. The resulting array of groups if the user was not.
1104
1125
  */
1105
- public $addGroup(group: Group & GroupData) {
1106
- if (this.$data.groups == null) {
1107
- this.$data.groups = [];
1126
+ public async $addGroup(group: Group & GroupData) {
1127
+ await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
1128
+ let groups = this.$data.groups;
1129
+ if (groups == null) {
1130
+ groups = [];
1108
1131
  }
1109
- if (!group.$inArray(this.$data.groups)) {
1110
- this.$data.groups.push(group);
1111
- return this.$data.groups;
1132
+ if (!group.$inArray(groups)) {
1133
+ groups.push(group);
1134
+ this.$data.groups = groups;
1135
+ return groups;
1112
1136
  }
1113
1137
  return true;
1114
1138
  }
@@ -1141,10 +1165,12 @@ export default class User extends AbleObject<UserData> {
1141
1165
  * @param group The group.
1142
1166
  * @returns True if the user wasn't in the group. The resulting array of groups if the user was.
1143
1167
  */
1144
- public $delGroup(group: Group & GroupData) {
1145
- if (this.$data.groups != null && group.$inArray(this.$data.groups)) {
1168
+ public async $delGroup(group: Group & GroupData) {
1169
+ await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
1170
+ let groups = this.$data.groups || [];
1171
+ if (this.$data.groups != null && group.$inArray(groups)) {
1146
1172
  const newGroups: (Group & GroupData)[] = [];
1147
- for (let curGroup of this.$data.groups) {
1173
+ for (let curGroup of groups) {
1148
1174
  if (!group.$is(curGroup)) {
1149
1175
  newGroups.push(curGroup);
1150
1176
  }
@@ -1161,7 +1187,7 @@ export default class User extends AbleObject<UserData> {
1161
1187
  * @param group The group, or the group's GUID.
1162
1188
  * @returns True or false.
1163
1189
  */
1164
- public $inGroup(group: (Group & GroupData) | string) {
1190
+ public async $inGroup(group: (Group & GroupData) | string) {
1165
1191
  if (typeof group === 'string') {
1166
1192
  if (this.$data.group?.guid === group) {
1167
1193
  return true;
@@ -1184,16 +1210,19 @@ export default class User extends AbleObject<UserData> {
1184
1210
  * @param group The group, or the group's GUID.
1185
1211
  * @returns True or false.
1186
1212
  */
1187
- public $isDescendant(group: (Group & GroupData) | string) {
1213
+ public async $isDescendant(group: (Group & GroupData) | string) {
1188
1214
  // Check to see if the user is in a descendant group of the given group.
1215
+ await this.$data.group?.$wake();
1189
1216
  if (
1217
+ this.$data.group != null &&
1190
1218
  this.$data.group?.cdate != null &&
1191
- this.$data.group.$isDescendant(group)
1219
+ (await this.$data.group?.$isDescendant(group))
1192
1220
  ) {
1193
1221
  return true;
1194
1222
  }
1223
+ await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
1195
1224
  for (let curGroup of this.$data.groups ?? []) {
1196
- if (curGroup.$isDescendant(group)) {
1225
+ if (await curGroup.$isDescendant(group)) {
1197
1226
  return true;
1198
1227
  }
1199
1228
  }
@@ -1224,7 +1253,7 @@ export default class User extends AbleObject<UserData> {
1224
1253
  if (await this.$save()) {
1225
1254
  if (data.revokeCurrentTokens) {
1226
1255
  const tilmeld = enforceTilmeld(this);
1227
- tilmeld.login(this, true);
1256
+ await tilmeld.login(this, true);
1228
1257
  }
1229
1258
  return { result: true, message: 'Your password has been changed.' };
1230
1259
  } else {
@@ -1277,7 +1306,7 @@ export default class User extends AbleObject<UserData> {
1277
1306
 
1278
1307
  if (await this.$save()) {
1279
1308
  const tilmeld = enforceTilmeld(this);
1280
- tilmeld.login(this, true);
1309
+ await tilmeld.login(this, true);
1281
1310
  return {
1282
1311
  result: true,
1283
1312
  message: 'You have logged out of all other sessions.',
@@ -1863,7 +1892,7 @@ export default class User extends AbleObject<UserData> {
1863
1892
  tilmeld.config.unverifiedAccess &&
1864
1893
  !madeAdmin
1865
1894
  ) {
1866
- if (!tilmeld.login(this, true)) {
1895
+ if (!(await tilmeld.login(this, true))) {
1867
1896
  throw new Error('An error occurred trying to log you in.');
1868
1897
  }
1869
1898
  message +=
@@ -1872,7 +1901,7 @@ export default class User extends AbleObject<UserData> {
1872
1901
  'registration.';
1873
1902
  loggedin = true;
1874
1903
  } else {
1875
- if (!tilmeld.login(this, true)) {
1904
+ if (!(await tilmeld.login(this, true))) {
1876
1905
  throw new Error('An error occurred trying to log you in.');
1877
1906
  }
1878
1907
  message += "You're now registered and logged in!";
@@ -1892,7 +1921,7 @@ export default class User extends AbleObject<UserData> {
1892
1921
  try {
1893
1922
  await tnymph.commit(transaction);
1894
1923
  this.$nymph = nymph;
1895
- this.$nymph.tilmeld?.fillSession(this);
1924
+ await this.$nymph.tilmeld?.fillSession(this);
1896
1925
  } catch (e: any) {
1897
1926
  throw e;
1898
1927
  }
@@ -1925,8 +1954,8 @@ export default class User extends AbleObject<UserData> {
1925
1954
  }
1926
1955
 
1927
1956
  if (
1928
- tilmeld.gatekeeper('tilmeld/admin') &&
1929
- !tilmeld.gatekeeper('system/admin') &&
1957
+ (await tilmeld.gatekeeper('tilmeld/admin')) &&
1958
+ !(await tilmeld.gatekeeper('system/admin')) &&
1930
1959
  this.$data.abilities?.includes('system/admin')
1931
1960
  ) {
1932
1961
  throw new BadDataError(
@@ -2020,7 +2049,7 @@ export default class User extends AbleObject<UserData> {
2020
2049
  }
2021
2050
 
2022
2051
  // Email changes.
2023
- if (!tilmeld.gatekeeper('tilmeld/admin')) {
2052
+ if (!(await tilmeld.gatekeeper('tilmeld/admin'))) {
2024
2053
  // The user isn't an admin, so email address changes should contain some
2025
2054
  // security measures.
2026
2055
  if (tilmeld.config.verifyEmail) {
@@ -2119,19 +2148,18 @@ export default class User extends AbleObject<UserData> {
2119
2148
  this.$nymph = tnymph;
2120
2149
  tilmeld = enforceTilmeld(this);
2121
2150
 
2122
- if (
2123
- this.$data.group != null &&
2124
- this.$data.group.user != null &&
2125
- this.$is(this.$data.group.user)
2126
- ) {
2151
+ const group = this.$data.group;
2152
+ await group?.$wake();
2153
+ if (group != null && group.user != null && this.$is(group.user)) {
2127
2154
  try {
2128
2155
  // Update the user's generated primary group.
2129
- this.$data.group.groupname = this.$data.username;
2130
- this.$data.group.avatar = this.$data.avatar;
2131
- this.$data.group.email = this.$data.email;
2132
- this.$data.group.name = this.$data.name;
2133
- this.$data.group.phone = this.$data.phone;
2134
- await this.$data.group.$saveSkipAC();
2156
+ group.groupname = this.$data.username;
2157
+ group.avatar = this.$data.avatar;
2158
+ group.email = this.$data.email;
2159
+ group.name = this.$data.name;
2160
+ group.phone = this.$data.phone;
2161
+ await group.$saveSkipAC();
2162
+ this.$data.group = group;
2135
2163
  } catch (e: any) {
2136
2164
  await tnymph.rollback(transaction);
2137
2165
  this.$nymph = nymph;
@@ -2168,9 +2196,11 @@ export default class User extends AbleObject<UserData> {
2168
2196
  this.$gatekeeperCache = undefined;
2169
2197
  await tnymph.commit(transaction);
2170
2198
 
2171
- if (enforceTilmeld(nymph).User.current(true).$is(this)) {
2199
+ const tilmeld = enforceTilmeld(nymph);
2200
+
2201
+ if (tilmeld.User.current(true).$is(this)) {
2172
2202
  // Update the user in the session cache.
2173
- enforceTilmeld(nymph).fillSession(this);
2203
+ await tilmeld.fillSession(this);
2174
2204
  }
2175
2205
  } else {
2176
2206
  await tnymph.rollback(transaction);
@@ -2197,11 +2227,11 @@ export default class User extends AbleObject<UserData> {
2197
2227
 
2198
2228
  public async $delete() {
2199
2229
  const tilmeld = enforceTilmeld(this);
2200
- if (!tilmeld.gatekeeper('tilmeld/admin')) {
2230
+ if (!(await tilmeld.gatekeeper('tilmeld/admin'))) {
2201
2231
  throw new BadDataError("You don't have the authority to delete users.");
2202
2232
  }
2203
2233
  if (
2204
- !tilmeld.gatekeeper('system/admin') &&
2234
+ !(await tilmeld.gatekeeper('system/admin')) &&
2205
2235
  this.$data.abilities?.includes('system/admin')
2206
2236
  ) {
2207
2237
  throw new BadDataError(