@nymphjs/tilmeld 1.0.0-beta.2 → 1.0.0-beta.21
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 +106 -0
- package/README.md +13 -0
- package/dist/Group.js +49 -23
- package/dist/Group.js.map +1 -1
- package/dist/Tilmeld.d.ts +5 -2
- package/dist/Tilmeld.js +151 -60
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +56 -3
- package/dist/User.js +306 -45
- package/dist/User.js.map +1 -1
- package/dist/conf/d.d.ts +3 -1
- package/dist/conf/defaults.js +15 -4
- 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 +22 -19
- package/src/Group.ts +70 -23
- package/src/Tilmeld.ts +225 -76
- package/src/User.ts +483 -49
- package/src/conf/d.ts +16 -7
- package/src/conf/defaults.ts +17 -4
- package/src/enforceTilmeld.ts +20 -0
- package/src/index.ts +2 -0
package/dist/User.js
CHANGED
|
@@ -3,12 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const guid_1 = require("@nymphjs/guid");
|
|
6
7
|
const strtotime_1 = __importDefault(require("locutus/php/datetime/strtotime"));
|
|
7
8
|
const enc_base64_1 = __importDefault(require("crypto-js/enc-base64"));
|
|
8
9
|
const sha256_1 = __importDefault(require("crypto-js/sha256"));
|
|
9
10
|
const md5_1 = __importDefault(require("crypto-js/md5"));
|
|
10
11
|
const lodash_1 = require("lodash");
|
|
11
|
-
const
|
|
12
|
+
const otpauth_1 = require("otpauth");
|
|
13
|
+
const qrcode_1 = require("qrcode");
|
|
14
|
+
const enforceTilmeld_1 = require("./enforceTilmeld");
|
|
12
15
|
const AbleObject_1 = __importDefault(require("./AbleObject"));
|
|
13
16
|
const errors_1 = require("./errors");
|
|
14
17
|
class User extends AbleObject_1.default {
|
|
@@ -185,7 +188,7 @@ class User extends AbleObject_1.default {
|
|
|
185
188
|
return result;
|
|
186
189
|
}
|
|
187
190
|
async $login(data) {
|
|
188
|
-
const tilmeld = this
|
|
191
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
189
192
|
if (this.guid == null) {
|
|
190
193
|
return { result: false, message: 'Incorrect login/password.' };
|
|
191
194
|
}
|
|
@@ -198,6 +201,20 @@ class User extends AbleObject_1.default {
|
|
|
198
201
|
if (!this.$checkPassword(data.password)) {
|
|
199
202
|
return { result: false, message: 'Incorrect login/password.' };
|
|
200
203
|
}
|
|
204
|
+
if (this.$data.totpSecret != null) {
|
|
205
|
+
if (data.code == null ||
|
|
206
|
+
typeof data.code !== 'string' ||
|
|
207
|
+
data.code.length !== 6) {
|
|
208
|
+
return {
|
|
209
|
+
result: false,
|
|
210
|
+
needTOTP: true,
|
|
211
|
+
message: 'You need to provide a 2FA code.',
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
if (!this.$checkTOTPCode(data.code)) {
|
|
215
|
+
return { result: false, message: 'Incorrect 2FA code.' };
|
|
216
|
+
}
|
|
217
|
+
}
|
|
201
218
|
try {
|
|
202
219
|
for (let callback of this.constructor
|
|
203
220
|
.beforeLoginCallbacks) {
|
|
@@ -223,8 +240,63 @@ class User extends AbleObject_1.default {
|
|
|
223
240
|
}
|
|
224
241
|
return { result: true, message: 'You are logged in.' };
|
|
225
242
|
}
|
|
243
|
+
async $switchUser(data) {
|
|
244
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
245
|
+
if (this.guid == null) {
|
|
246
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
247
|
+
}
|
|
248
|
+
let user = tilmeld.User.current();
|
|
249
|
+
if (!user || user.guid == null) {
|
|
250
|
+
return { result: false, message: "You're not logged in." };
|
|
251
|
+
}
|
|
252
|
+
const isCurrentUser = user != null && user.$is(this);
|
|
253
|
+
if (isCurrentUser) {
|
|
254
|
+
return { result: false, message: "You can't switch to yourself." };
|
|
255
|
+
}
|
|
256
|
+
const toAbilities = this.$data.abilities || [];
|
|
257
|
+
const fromAbilities = user.abilities || [];
|
|
258
|
+
if (fromAbilities.indexOf('tilmeld/switch') === -1 &&
|
|
259
|
+
fromAbilities.indexOf('system/admin') === -1) {
|
|
260
|
+
return {
|
|
261
|
+
result: false,
|
|
262
|
+
message: "You don't have permission to switch users.",
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
if (toAbilities.indexOf('system/admin') !== -1 ||
|
|
266
|
+
toAbilities.indexOf('tilmeld/admin') !== -1) {
|
|
267
|
+
return { result: false, message: "You can't switch to an admin." };
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
for (let callback of this.constructor
|
|
271
|
+
.beforeLoginCallbacks) {
|
|
272
|
+
if (callback) {
|
|
273
|
+
await callback(this, {
|
|
274
|
+
username: this.$data.username || '',
|
|
275
|
+
password: '',
|
|
276
|
+
...(data || {}),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
return {
|
|
283
|
+
result: false,
|
|
284
|
+
message: e.message,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (!tilmeld.loginSwitch(this, true)) {
|
|
288
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
289
|
+
}
|
|
290
|
+
for (let callback of this.constructor
|
|
291
|
+
.afterLoginCallbacks) {
|
|
292
|
+
if (callback) {
|
|
293
|
+
await callback(this);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return { result: true, message: 'You are logged in.' };
|
|
297
|
+
}
|
|
226
298
|
async $logout() {
|
|
227
|
-
const tilmeld = this
|
|
299
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
228
300
|
try {
|
|
229
301
|
for (let callback of this.constructor
|
|
230
302
|
.beforeLogoutCallbacks) {
|
|
@@ -284,25 +356,49 @@ class User extends AbleObject_1.default {
|
|
|
284
356
|
return this.$descendantGroups;
|
|
285
357
|
}
|
|
286
358
|
$jsonAcceptData(input, allowConflict = false) {
|
|
287
|
-
const tilmeld = this
|
|
359
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
288
360
|
this.$referenceWake();
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
|
|
361
|
+
if ('abilities' in input.data &&
|
|
362
|
+
input.data.abilities?.includes('system/admin') !==
|
|
363
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
364
|
+
!tilmeld.gatekeeper('system/admin')) {
|
|
365
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke system/admin.");
|
|
366
|
+
}
|
|
367
|
+
if ('abilities' in input.data &&
|
|
368
|
+
input.data.abilities?.includes('tilmeld/admin') !==
|
|
369
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
292
370
|
!tilmeld.gatekeeper('system/admin')) {
|
|
293
|
-
throw new errors_1.BadDataError("You don't have the authority to
|
|
371
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/admin.");
|
|
372
|
+
}
|
|
373
|
+
if ('abilities' in input.data &&
|
|
374
|
+
input.data.abilities?.includes('tilmeld/switch') !==
|
|
375
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
376
|
+
!tilmeld.gatekeeper('system/admin')) {
|
|
377
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/switch.");
|
|
294
378
|
}
|
|
295
379
|
this.$originalEmail = this.$data.email;
|
|
296
380
|
super.$jsonAcceptData(input, allowConflict);
|
|
297
381
|
}
|
|
298
382
|
$jsonAcceptPatch(patch, allowConflict = false) {
|
|
299
|
-
const tilmeld = this
|
|
383
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
300
384
|
this.$referenceWake();
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
385
|
+
if ('abilities' in patch.set &&
|
|
386
|
+
patch.set.abilities?.includes('system/admin') !==
|
|
387
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
388
|
+
!tilmeld.gatekeeper('system/admin')) {
|
|
389
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke system/admin.");
|
|
390
|
+
}
|
|
391
|
+
if ('abilities' in patch.set &&
|
|
392
|
+
patch.set.abilities?.includes('tilmeld/admin') !==
|
|
393
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
304
394
|
!tilmeld.gatekeeper('system/admin')) {
|
|
305
|
-
throw new errors_1.BadDataError("You don't have the authority to
|
|
395
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/admin.");
|
|
396
|
+
}
|
|
397
|
+
if ('abilities' in patch.set &&
|
|
398
|
+
patch.set.abilities?.includes('tilmeld/switch') !==
|
|
399
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
400
|
+
!tilmeld.gatekeeper('system/admin')) {
|
|
401
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/switch.");
|
|
306
402
|
}
|
|
307
403
|
this.$originalEmail = this.$data.email;
|
|
308
404
|
super.$jsonAcceptPatch(patch, allowConflict);
|
|
@@ -312,7 +408,7 @@ class User extends AbleObject_1.default {
|
|
|
312
408
|
this.$updateDataProtection();
|
|
313
409
|
}
|
|
314
410
|
$updateDataProtection(givenUser) {
|
|
315
|
-
const tilmeld = this
|
|
411
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
316
412
|
let user = givenUser ?? tilmeld.User.current();
|
|
317
413
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
318
414
|
this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
@@ -328,13 +424,18 @@ class User extends AbleObject_1.default {
|
|
|
328
424
|
if (isCurrentUser) {
|
|
329
425
|
this.$clientEnabledMethods.push('$gatekeeper');
|
|
330
426
|
this.$clientEnabledMethods.push('$changePassword');
|
|
427
|
+
this.$clientEnabledMethods.push('$revokeCurrentTokens');
|
|
331
428
|
this.$clientEnabledMethods.push('$logout');
|
|
332
429
|
this.$clientEnabledMethods.push('$sendEmailVerification');
|
|
430
|
+
this.$clientEnabledMethods.push('$hasTOTPSecret');
|
|
431
|
+
this.$clientEnabledMethods.push('$getNewTOTPSecret');
|
|
432
|
+
this.$clientEnabledMethods.push('$saveTOTPSecret');
|
|
433
|
+
this.$clientEnabledMethods.push('$removeTOTPSecret');
|
|
333
434
|
}
|
|
334
435
|
if (user != null &&
|
|
335
436
|
(abilities.indexOf('tilmeld/admin') !== -1 ||
|
|
336
437
|
abilities.indexOf('system/admin') !== -1)) {
|
|
337
|
-
this.$privateData = ['password', 'salt'];
|
|
438
|
+
this.$privateData = ['password', 'salt', 'totpSecret'];
|
|
338
439
|
this.$allowlistData = undefined;
|
|
339
440
|
}
|
|
340
441
|
else if (isCurrentUser || isNewUser) {
|
|
@@ -355,20 +456,29 @@ class User extends AbleObject_1.default {
|
|
|
355
456
|
this.$allowlistData.push('phone');
|
|
356
457
|
}
|
|
357
458
|
this.$privateData = [
|
|
459
|
+
'enabled',
|
|
358
460
|
'secret',
|
|
461
|
+
'emailChangeDate',
|
|
359
462
|
'newEmailSecret',
|
|
360
|
-
'cancelEmailAddress',
|
|
361
463
|
'cancelEmailSecret',
|
|
362
|
-
'
|
|
464
|
+
'cancelEmailAddress',
|
|
363
465
|
'recoverSecret',
|
|
364
466
|
'recoverSecretDate',
|
|
365
|
-
'password',
|
|
366
467
|
'salt',
|
|
468
|
+
'password',
|
|
469
|
+
'passwordTemp',
|
|
470
|
+
'totpSecret',
|
|
367
471
|
];
|
|
368
472
|
}
|
|
473
|
+
if (user != null &&
|
|
474
|
+
!isCurrentUser &&
|
|
475
|
+
(abilities.indexOf('tilmeld/switch') !== -1 ||
|
|
476
|
+
abilities.indexOf('system/admin') !== -1)) {
|
|
477
|
+
this.$clientEnabledMethods.push('$switchUser');
|
|
478
|
+
}
|
|
369
479
|
}
|
|
370
480
|
$gatekeeper(ability) {
|
|
371
|
-
const tilmeld = this
|
|
481
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
372
482
|
if (ability == null) {
|
|
373
483
|
return tilmeld.User.current()?.$is(this) ?? false;
|
|
374
484
|
}
|
|
@@ -389,7 +499,7 @@ class User extends AbleObject_1.default {
|
|
|
389
499
|
this.$gatekeeperCache = Object.fromEntries(abilities.map((ability) => [ability, true]));
|
|
390
500
|
}
|
|
391
501
|
return ((ability in this.$gatekeeperCache && !!this.$gatekeeperCache[ability]) ||
|
|
392
|
-
!!this.$
|
|
502
|
+
!!this.$data.abilities?.includes('system/admin'));
|
|
393
503
|
}
|
|
394
504
|
$clearCache() {
|
|
395
505
|
const ret = super.$clearCache();
|
|
@@ -398,7 +508,7 @@ class User extends AbleObject_1.default {
|
|
|
398
508
|
return ret;
|
|
399
509
|
}
|
|
400
510
|
async $sendEmailVerification() {
|
|
401
|
-
const tilmeld = this
|
|
511
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
402
512
|
if (this.guid == null) {
|
|
403
513
|
return false;
|
|
404
514
|
}
|
|
@@ -472,7 +582,7 @@ class User extends AbleObject_1.default {
|
|
|
472
582
|
return true;
|
|
473
583
|
}
|
|
474
584
|
$checkPassword(password) {
|
|
475
|
-
const tilmeld = this
|
|
585
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
476
586
|
switch (tilmeld.config.pwMethod) {
|
|
477
587
|
case 'plain':
|
|
478
588
|
return this.$data.password === password;
|
|
@@ -531,7 +641,14 @@ class User extends AbleObject_1.default {
|
|
|
531
641
|
return { result: false, message: 'Incorrect password.' };
|
|
532
642
|
}
|
|
533
643
|
this.$data.passwordTemp = data.newPassword;
|
|
644
|
+
if (data.revokeCurrentTokens) {
|
|
645
|
+
this.$data.revokeTokenDate = Date.now();
|
|
646
|
+
}
|
|
534
647
|
if (await this.$save()) {
|
|
648
|
+
if (data.revokeCurrentTokens) {
|
|
649
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
650
|
+
tilmeld.login(this, true);
|
|
651
|
+
}
|
|
535
652
|
return { result: true, message: 'Your password has been changed.' };
|
|
536
653
|
}
|
|
537
654
|
else {
|
|
@@ -539,7 +656,7 @@ class User extends AbleObject_1.default {
|
|
|
539
656
|
}
|
|
540
657
|
}
|
|
541
658
|
$password(password) {
|
|
542
|
-
const tilmeld = this
|
|
659
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
543
660
|
switch (tilmeld.config.pwMethod) {
|
|
544
661
|
case 'plain':
|
|
545
662
|
delete this.$data.salt;
|
|
@@ -557,8 +674,137 @@ class User extends AbleObject_1.default {
|
|
|
557
674
|
}
|
|
558
675
|
return this.$data.password;
|
|
559
676
|
}
|
|
677
|
+
async $revokeCurrentTokens(data) {
|
|
678
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
679
|
+
return { result: false, message: 'Incorrect password.' };
|
|
680
|
+
}
|
|
681
|
+
this.$data.revokeTokenDate = Date.now();
|
|
682
|
+
if (await this.$save()) {
|
|
683
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
684
|
+
tilmeld.login(this, true);
|
|
685
|
+
return {
|
|
686
|
+
result: true,
|
|
687
|
+
message: 'You have logged out of all other sessions.',
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
return { result: false, message: "Couldn't save revocation date." };
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
async $hasTOTPSecret() {
|
|
695
|
+
return this.$data.totpSecret != null;
|
|
696
|
+
}
|
|
697
|
+
$checkTOTPCode(code) {
|
|
698
|
+
if (this.$data.totpSecret == null) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
702
|
+
const totp = new otpauth_1.TOTP({
|
|
703
|
+
issuer: tilmeld.config.appName,
|
|
704
|
+
label: this.$data.username,
|
|
705
|
+
algorithm: 'SHA1',
|
|
706
|
+
digits: 6,
|
|
707
|
+
period: 30,
|
|
708
|
+
secret: this.$data.totpSecret,
|
|
709
|
+
});
|
|
710
|
+
return totp.validate({ token: code, window: 2 }) != null;
|
|
711
|
+
}
|
|
712
|
+
async $getNewTOTPSecret() {
|
|
713
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
714
|
+
if (this.$data.totpSecret != null) {
|
|
715
|
+
throw new errors_1.BadDataError('You already have a 2FA secret.');
|
|
716
|
+
}
|
|
717
|
+
const secret = new otpauth_1.Secret();
|
|
718
|
+
const totp = new otpauth_1.TOTP({
|
|
719
|
+
issuer: tilmeld.config.appName,
|
|
720
|
+
label: this.$data.username,
|
|
721
|
+
algorithm: 'SHA1',
|
|
722
|
+
digits: 6,
|
|
723
|
+
period: 30,
|
|
724
|
+
secret,
|
|
725
|
+
});
|
|
726
|
+
const uri = totp.toString();
|
|
727
|
+
const qrcode = await (0, qrcode_1.toDataURL)(uri);
|
|
728
|
+
return {
|
|
729
|
+
uri,
|
|
730
|
+
qrcode,
|
|
731
|
+
secret: secret.base32,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
async $saveTOTPSecret(data) {
|
|
735
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
736
|
+
return { result: false, message: 'Incorrect password.' };
|
|
737
|
+
}
|
|
738
|
+
if (this.$data.totpSecret != null) {
|
|
739
|
+
return { result: false, message: 'You already have a 2FA secret.' };
|
|
740
|
+
}
|
|
741
|
+
if (data.secret == null ||
|
|
742
|
+
typeof data.secret !== 'string' ||
|
|
743
|
+
data.secret === '') {
|
|
744
|
+
return { result: false, message: '2FA secret is invalid.' };
|
|
745
|
+
}
|
|
746
|
+
if (data.code == null ||
|
|
747
|
+
typeof data.code !== 'string' ||
|
|
748
|
+
data.code.length !== 6) {
|
|
749
|
+
return { result: false, message: '2FA code is invalid.' };
|
|
750
|
+
}
|
|
751
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
752
|
+
const totp = new otpauth_1.TOTP({
|
|
753
|
+
issuer: tilmeld.config.appName,
|
|
754
|
+
label: this.$data.username,
|
|
755
|
+
algorithm: 'SHA1',
|
|
756
|
+
digits: 6,
|
|
757
|
+
period: 30,
|
|
758
|
+
secret: data.secret,
|
|
759
|
+
});
|
|
760
|
+
if (totp.validate({ token: data.code, window: 2 }) == null) {
|
|
761
|
+
return { result: false, message: '2FA code is incorrect.' };
|
|
762
|
+
}
|
|
763
|
+
this.$data.totpSecret = data.secret;
|
|
764
|
+
if (await this.$save()) {
|
|
765
|
+
return { result: true, message: 'Your two factor secret is now set.' };
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
return { result: false, message: "Couldn't save two factor secret." };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
async $removeTOTPSecret(data) {
|
|
772
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
773
|
+
return { result: false, message: 'Incorrect password.' };
|
|
774
|
+
}
|
|
775
|
+
if (this.$data.totpSecret == null) {
|
|
776
|
+
return { result: false, message: "You don't have a 2FA secret." };
|
|
777
|
+
}
|
|
778
|
+
if (data.code == null ||
|
|
779
|
+
typeof data.code !== 'string' ||
|
|
780
|
+
data.code.length !== 6) {
|
|
781
|
+
return { result: false, message: '2FA code is invalid.' };
|
|
782
|
+
}
|
|
783
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
784
|
+
const totp = new otpauth_1.TOTP({
|
|
785
|
+
issuer: tilmeld.config.appName,
|
|
786
|
+
label: this.$data.username,
|
|
787
|
+
algorithm: 'SHA1',
|
|
788
|
+
digits: 6,
|
|
789
|
+
period: 30,
|
|
790
|
+
secret: this.$data.totpSecret,
|
|
791
|
+
});
|
|
792
|
+
if (totp.validate({ token: data.code, window: 2 }) == null) {
|
|
793
|
+
return { result: false, message: '2FA code is incorrect.' };
|
|
794
|
+
}
|
|
795
|
+
delete this.$data.totpSecret;
|
|
796
|
+
if (await this.$save()) {
|
|
797
|
+
return {
|
|
798
|
+
result: true,
|
|
799
|
+
message: 'Your two factor secret has been removed.',
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
else {
|
|
803
|
+
return { result: false, message: "Couldn't remove two factor secret." };
|
|
804
|
+
}
|
|
805
|
+
}
|
|
560
806
|
async $checkUsername() {
|
|
561
|
-
const tilmeld = this
|
|
807
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
562
808
|
if (!tilmeld.config.emailUsernames) {
|
|
563
809
|
if (this.$data.username == null || !this.$data.username.length) {
|
|
564
810
|
return { result: false, message: 'Please specify a username.' };
|
|
@@ -598,6 +844,17 @@ class User extends AbleObject_1.default {
|
|
|
598
844
|
if (test != null) {
|
|
599
845
|
return { result: false, message: 'That username is taken.' };
|
|
600
846
|
}
|
|
847
|
+
for (let callback of this.constructor
|
|
848
|
+
.checkUsernameCallbacks) {
|
|
849
|
+
if (callback) {
|
|
850
|
+
const result = await callback(this, {
|
|
851
|
+
username: this.$data.username,
|
|
852
|
+
});
|
|
853
|
+
if (!result.result) {
|
|
854
|
+
return { message: 'Username is not available.', ...result };
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
601
858
|
return {
|
|
602
859
|
result: true,
|
|
603
860
|
message: this.guid != null ? 'Username is valid.' : 'Username is available!',
|
|
@@ -621,7 +878,7 @@ class User extends AbleObject_1.default {
|
|
|
621
878
|
}
|
|
622
879
|
}
|
|
623
880
|
async $checkEmail() {
|
|
624
|
-
const tilmeld = this
|
|
881
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
625
882
|
if (this.$data.email == null || !this.$data.email.length) {
|
|
626
883
|
if (tilmeld.config.verifyEmail) {
|
|
627
884
|
return { result: false, message: 'Please specify an email.' };
|
|
@@ -656,7 +913,7 @@ class User extends AbleObject_1.default {
|
|
|
656
913
|
};
|
|
657
914
|
}
|
|
658
915
|
async $checkPhone() {
|
|
659
|
-
const tilmeld = this
|
|
916
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
660
917
|
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
661
918
|
return { result: false, message: 'Please specify a phone number.' };
|
|
662
919
|
}
|
|
@@ -684,7 +941,7 @@ class User extends AbleObject_1.default {
|
|
|
684
941
|
};
|
|
685
942
|
}
|
|
686
943
|
async $register(data) {
|
|
687
|
-
let tilmeld = this
|
|
944
|
+
let tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
688
945
|
if (!tilmeld.config.allowRegistration) {
|
|
689
946
|
return {
|
|
690
947
|
result: false,
|
|
@@ -742,7 +999,7 @@ class User extends AbleObject_1.default {
|
|
|
742
999
|
const nymph = this.$nymph;
|
|
743
1000
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
744
1001
|
this.$nymph = tnymph;
|
|
745
|
-
tilmeld = this
|
|
1002
|
+
tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
746
1003
|
try {
|
|
747
1004
|
let generatedPrimaryGroup = null;
|
|
748
1005
|
if (tilmeld.config.generatePrimary) {
|
|
@@ -909,13 +1166,13 @@ class User extends AbleObject_1.default {
|
|
|
909
1166
|
}
|
|
910
1167
|
}
|
|
911
1168
|
async $save() {
|
|
912
|
-
let tilmeld = this
|
|
1169
|
+
let tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
913
1170
|
if (this.$data.username == null || !this.$data.username.trim().length) {
|
|
914
1171
|
return false;
|
|
915
1172
|
}
|
|
916
1173
|
if (tilmeld.gatekeeper('tilmeld/admin') &&
|
|
917
1174
|
!tilmeld.gatekeeper('system/admin') &&
|
|
918
|
-
this.$
|
|
1175
|
+
this.$data.abilities?.includes('system/admin')) {
|
|
919
1176
|
throw new errors_1.BadDataError("You don't have the authority to modify system admins.");
|
|
920
1177
|
}
|
|
921
1178
|
let sendVerification = false;
|
|
@@ -1062,7 +1319,7 @@ class User extends AbleObject_1.default {
|
|
|
1062
1319
|
const nymph = this.$nymph;
|
|
1063
1320
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1064
1321
|
this.$nymph = tnymph;
|
|
1065
|
-
tilmeld = this
|
|
1322
|
+
tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
1066
1323
|
if (this.$data.group != null &&
|
|
1067
1324
|
this.$data.group.user != null &&
|
|
1068
1325
|
this.$is(this.$data.group.user)) {
|
|
@@ -1106,8 +1363,8 @@ class User extends AbleObject_1.default {
|
|
|
1106
1363
|
this.$descendantGroups = undefined;
|
|
1107
1364
|
this.$gatekeeperCache = undefined;
|
|
1108
1365
|
await tnymph.commit(transaction);
|
|
1109
|
-
if (nymph.
|
|
1110
|
-
nymph.
|
|
1366
|
+
if ((0, enforceTilmeld_1.enforceTilmeld)(nymph).User.current(true).$is(this)) {
|
|
1367
|
+
(0, enforceTilmeld_1.enforceTilmeld)(nymph).fillSession(this);
|
|
1111
1368
|
}
|
|
1112
1369
|
}
|
|
1113
1370
|
else {
|
|
@@ -1128,12 +1385,12 @@ class User extends AbleObject_1.default {
|
|
|
1128
1385
|
return false;
|
|
1129
1386
|
}
|
|
1130
1387
|
async $delete() {
|
|
1131
|
-
const tilmeld = this
|
|
1388
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
1132
1389
|
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1133
1390
|
throw new errors_1.BadDataError("You don't have the authority to delete users.");
|
|
1134
1391
|
}
|
|
1135
1392
|
if (!tilmeld.gatekeeper('system/admin') &&
|
|
1136
|
-
this.$
|
|
1393
|
+
this.$data.abilities?.includes('system/admin')) {
|
|
1137
1394
|
throw new errors_1.BadDataError("You don't have the authority to delete system admins.");
|
|
1138
1395
|
}
|
|
1139
1396
|
if (tilmeld.User.current(true).$is(this)) {
|
|
@@ -1161,9 +1418,9 @@ class User extends AbleObject_1.default {
|
|
|
1161
1418
|
return true;
|
|
1162
1419
|
}
|
|
1163
1420
|
}
|
|
1164
|
-
exports.default = User;
|
|
1165
1421
|
User.ETYPE = 'tilmeld_user';
|
|
1166
1422
|
User.class = 'User';
|
|
1423
|
+
User.checkUsernameCallbacks = [];
|
|
1167
1424
|
User.beforeRegisterCallbacks = [];
|
|
1168
1425
|
User.afterRegisterCallbacks = [];
|
|
1169
1426
|
User.beforeLoginCallbacks = [];
|
|
@@ -1178,23 +1435,26 @@ User.DEFAULT_CLIENT_ENABLED_METHODS = [
|
|
|
1178
1435
|
'$register',
|
|
1179
1436
|
];
|
|
1180
1437
|
User.DEFAULT_PRIVATE_DATA = [
|
|
1438
|
+
'abilities',
|
|
1181
1439
|
'email',
|
|
1182
|
-
'originalEmail',
|
|
1183
1440
|
'phone',
|
|
1184
1441
|
'group',
|
|
1185
1442
|
'groups',
|
|
1186
|
-
'abilities',
|
|
1187
1443
|
'inheritAbilities',
|
|
1188
|
-
'
|
|
1189
|
-
'recoverSecretDate',
|
|
1190
|
-
'password',
|
|
1191
|
-
'salt',
|
|
1444
|
+
'enabled',
|
|
1192
1445
|
'secret',
|
|
1193
|
-
'
|
|
1446
|
+
'emailChangeDate',
|
|
1194
1447
|
'newEmailSecret',
|
|
1195
|
-
'
|
|
1448
|
+
'newEmailAddress',
|
|
1196
1449
|
'cancelEmailSecret',
|
|
1197
|
-
'
|
|
1450
|
+
'cancelEmailAddress',
|
|
1451
|
+
'recoverSecret',
|
|
1452
|
+
'recoverSecretDate',
|
|
1453
|
+
'salt',
|
|
1454
|
+
'password',
|
|
1455
|
+
'passwordTemp',
|
|
1456
|
+
'revokeTokenDate',
|
|
1457
|
+
'totpSecret',
|
|
1198
1458
|
];
|
|
1199
1459
|
User.DEFAULT_ALLOWLIST_DATA = [];
|
|
1200
1460
|
User.clientEnabledStaticMethods = [
|
|
@@ -1205,4 +1465,5 @@ User.clientEnabledStaticMethods = [
|
|
|
1205
1465
|
'getClientConfig',
|
|
1206
1466
|
];
|
|
1207
1467
|
User.searchRestrictedData = [...User.DEFAULT_PRIVATE_DATA];
|
|
1468
|
+
exports.default = User;
|
|
1208
1469
|
//# sourceMappingURL=User.js.map
|