@nymphjs/tilmeld 1.0.0-alpha.3 → 1.0.0-alpha.33
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 +151 -0
- package/dist/Group.js +11 -6
- package/dist/Group.js.map +1 -1
- package/dist/Group.test.js +6 -0
- package/dist/Group.test.js.map +1 -1
- package/dist/Tilmeld.d.ts +3 -6
- package/dist/Tilmeld.js +196 -90
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +40 -2
- package/dist/User.js +109 -7
- package/dist/User.js.map +1 -1
- package/dist/User.test.js +6 -0
- package/dist/User.test.js.map +1 -1
- package/dist/conf/d.d.ts +3 -0
- package/dist/conf/defaults.js +25 -101
- package/dist/conf/defaults.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -1
- 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 +16 -16
- package/src/Group.test.ts +8 -0
- package/src/Group.ts +21 -7
- package/src/Tilmeld.ts +300 -108
- package/src/User.test.ts +8 -0
- package/src/User.ts +235 -10
- package/src/conf/d.ts +30 -0
- package/src/conf/defaults.ts +10 -57
- package/src/index.ts +3 -0
- package/src/tilmeldJoiProps.ts +46 -0
package/src/User.test.ts
CHANGED
|
@@ -40,6 +40,14 @@ describe('User', () => {
|
|
|
40
40
|
return newUser;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
it('new user passes validation', async () => {
|
|
44
|
+
const validUser = await makeNewUser();
|
|
45
|
+
|
|
46
|
+
expect(() => {
|
|
47
|
+
defaults.validatorUser(validUser);
|
|
48
|
+
}).not.toThrow();
|
|
49
|
+
});
|
|
50
|
+
|
|
43
51
|
it("doesn't allow unknown keys", async () => {
|
|
44
52
|
const invalidUser = await makeNewUser();
|
|
45
53
|
|
package/src/User.ts
CHANGED
|
@@ -24,6 +24,44 @@ import {
|
|
|
24
24
|
EmailChangeRateLimitExceededError,
|
|
25
25
|
} from './errors';
|
|
26
26
|
|
|
27
|
+
export type EventType =
|
|
28
|
+
| 'beforeRegister'
|
|
29
|
+
| 'afterRegister'
|
|
30
|
+
| 'beforeLogin'
|
|
31
|
+
| 'afterLogin'
|
|
32
|
+
| 'beforeLogout'
|
|
33
|
+
| 'afterLogout';
|
|
34
|
+
/**
|
|
35
|
+
* Theses are run before the user data checks, so the only checks before are
|
|
36
|
+
* whether registration is allowed and whether the user is already registered.
|
|
37
|
+
*/
|
|
38
|
+
export type TilmeldBeforeRegisterCallback = (
|
|
39
|
+
user: User & UserData,
|
|
40
|
+
data: { password: string; additionalData?: { [k: string]: any } }
|
|
41
|
+
) => Promise<void> | void;
|
|
42
|
+
export type TilmeldAfterRegisterCallback = (
|
|
43
|
+
user: User & UserData,
|
|
44
|
+
result: { loggedin: boolean; message: string }
|
|
45
|
+
) => Promise<void> | void;
|
|
46
|
+
/**
|
|
47
|
+
* These are run after the authentication checks, but before the login action.
|
|
48
|
+
*/
|
|
49
|
+
export type TilmeldBeforeLoginCallback = (
|
|
50
|
+
user: User & UserData,
|
|
51
|
+
data: {
|
|
52
|
+
username: string;
|
|
53
|
+
password: string;
|
|
54
|
+
additionalData?: { [k: string]: any };
|
|
55
|
+
}
|
|
56
|
+
) => void;
|
|
57
|
+
/**
|
|
58
|
+
* This is run before the transaction is committed, and you can perform
|
|
59
|
+
* additional functions on the transaction, which is available in `user.$nymph`.
|
|
60
|
+
*/
|
|
61
|
+
export type TilmeldAfterLoginCallback = (user: User & UserData) => void;
|
|
62
|
+
export type TilmeldBeforeLogoutCallback = (user: User & UserData) => void;
|
|
63
|
+
export type TilmeldAfterLogoutCallback = (user: User & UserData) => void;
|
|
64
|
+
|
|
27
65
|
export type UserData = {
|
|
28
66
|
/**
|
|
29
67
|
* The abilities granted to the user.
|
|
@@ -126,13 +164,28 @@ export type UserData = {
|
|
|
126
164
|
passwordTemp?: string;
|
|
127
165
|
};
|
|
128
166
|
|
|
167
|
+
/**
|
|
168
|
+
* A user data model.
|
|
169
|
+
*
|
|
170
|
+
* Written by Hunter Perrin for SciActive.
|
|
171
|
+
*
|
|
172
|
+
* @author Hunter Perrin <hperrin@gmail.com>
|
|
173
|
+
* @copyright SciActive Inc
|
|
174
|
+
* @see http://nymph.io/
|
|
175
|
+
*/
|
|
129
176
|
export default class User extends AbleObject<UserData> {
|
|
130
177
|
/**
|
|
131
178
|
* The instance of Tilmeld to use for queries.
|
|
132
179
|
*/
|
|
133
|
-
|
|
180
|
+
static tilmeld: Tilmeld;
|
|
134
181
|
static ETYPE = 'tilmeld_user';
|
|
135
182
|
static class = 'User';
|
|
183
|
+
private static beforeRegisterCallbacks: TilmeldBeforeRegisterCallback[] = [];
|
|
184
|
+
private static afterRegisterCallbacks: TilmeldAfterRegisterCallback[] = [];
|
|
185
|
+
private static beforeLoginCallbacks: TilmeldBeforeLoginCallback[] = [];
|
|
186
|
+
private static afterLoginCallbacks: TilmeldAfterLoginCallback[] = [];
|
|
187
|
+
private static beforeLogoutCallbacks: TilmeldBeforeLogoutCallback[] = [];
|
|
188
|
+
private static afterLogoutCallbacks: TilmeldAfterLogoutCallback[] = [];
|
|
136
189
|
|
|
137
190
|
private static DEFAULT_CLIENT_ENABLED_METHODS = [
|
|
138
191
|
'$checkUsername',
|
|
@@ -162,7 +215,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
162
215
|
];
|
|
163
216
|
private static DEFAULT_ALLOWLIST_DATA: string[] = [];
|
|
164
217
|
|
|
165
|
-
protected $clientEnabledMethods = User.DEFAULT_CLIENT_ENABLED_METHODS;
|
|
218
|
+
protected $clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
166
219
|
public static clientEnabledStaticMethods = [
|
|
167
220
|
'current',
|
|
168
221
|
'loginUser',
|
|
@@ -170,9 +223,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
170
223
|
'recover',
|
|
171
224
|
'getClientConfig',
|
|
172
225
|
];
|
|
173
|
-
protected $privateData = User.DEFAULT_PRIVATE_DATA;
|
|
174
|
-
public static searchRestrictedData = User.DEFAULT_PRIVATE_DATA;
|
|
175
|
-
protected $allowlistData? = User.DEFAULT_ALLOWLIST_DATA;
|
|
226
|
+
protected $privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
227
|
+
public static searchRestrictedData = [...User.DEFAULT_PRIVATE_DATA];
|
|
228
|
+
protected $allowlistData? = [...User.DEFAULT_ALLOWLIST_DATA];
|
|
176
229
|
protected $allowlistTags?: string[] = [];
|
|
177
230
|
|
|
178
231
|
/**
|
|
@@ -420,7 +473,11 @@ export default class User extends AbleObject<UserData> {
|
|
|
420
473
|
};
|
|
421
474
|
}
|
|
422
475
|
|
|
423
|
-
public static async loginUser(data: {
|
|
476
|
+
public static async loginUser(data: {
|
|
477
|
+
username: string;
|
|
478
|
+
password: string;
|
|
479
|
+
additionalData?: { [k: string]: any };
|
|
480
|
+
}) {
|
|
424
481
|
if (!('username' in data) || !data.username.length) {
|
|
425
482
|
return { result: false, message: 'Incorrect login/password.' };
|
|
426
483
|
}
|
|
@@ -434,7 +491,11 @@ export default class User extends AbleObject<UserData> {
|
|
|
434
491
|
return result;
|
|
435
492
|
}
|
|
436
493
|
|
|
437
|
-
public $login(data: {
|
|
494
|
+
public $login(data: {
|
|
495
|
+
username: string;
|
|
496
|
+
password: string;
|
|
497
|
+
additionalData?: { [k: string]: any };
|
|
498
|
+
}) {
|
|
438
499
|
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
439
500
|
if (this.guid == null) {
|
|
440
501
|
return { result: false, message: 'Incorrect login/password.' };
|
|
@@ -449,11 +510,32 @@ export default class User extends AbleObject<UserData> {
|
|
|
449
510
|
return { result: false, message: 'Incorrect login/password.' };
|
|
450
511
|
}
|
|
451
512
|
|
|
513
|
+
try {
|
|
514
|
+
for (let callback of (this.constructor as typeof User)
|
|
515
|
+
.beforeLoginCallbacks) {
|
|
516
|
+
if (callback) {
|
|
517
|
+
callback(this, data);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
} catch (e: any) {
|
|
521
|
+
return {
|
|
522
|
+
result: false,
|
|
523
|
+
message: e.message,
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
|
|
452
527
|
// Authentication was successful, attempt to login.
|
|
453
528
|
if (!tilmeld.login(this, true)) {
|
|
454
529
|
return { result: false, message: 'Incorrect login/password.' };
|
|
455
530
|
}
|
|
456
531
|
|
|
532
|
+
for (let callback of (this.constructor as typeof User)
|
|
533
|
+
.afterLoginCallbacks) {
|
|
534
|
+
if (callback) {
|
|
535
|
+
callback(this);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
457
539
|
// Login was successful.
|
|
458
540
|
return { result: true, message: 'You are logged in.' };
|
|
459
541
|
}
|
|
@@ -464,7 +546,30 @@ export default class User extends AbleObject<UserData> {
|
|
|
464
546
|
*/
|
|
465
547
|
public $logout() {
|
|
466
548
|
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
549
|
+
|
|
550
|
+
try {
|
|
551
|
+
for (let callback of (this.constructor as typeof User)
|
|
552
|
+
.beforeLogoutCallbacks) {
|
|
553
|
+
if (callback) {
|
|
554
|
+
callback(this);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
} catch (e: any) {
|
|
558
|
+
return {
|
|
559
|
+
result: false,
|
|
560
|
+
message: e.message,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
467
564
|
tilmeld.logout();
|
|
565
|
+
|
|
566
|
+
for (let callback of (this.constructor as typeof User)
|
|
567
|
+
.afterLogoutCallbacks) {
|
|
568
|
+
if (callback) {
|
|
569
|
+
callback(this);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
468
573
|
return { result: true, message: 'You have been logged out.' };
|
|
469
574
|
}
|
|
470
575
|
|
|
@@ -570,9 +675,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
570
675
|
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
571
676
|
let user = givenUser ?? tilmeld.User.current();
|
|
572
677
|
|
|
573
|
-
this.$clientEnabledMethods = User.DEFAULT_CLIENT_ENABLED_METHODS;
|
|
574
|
-
this.$privateData = User.DEFAULT_PRIVATE_DATA;
|
|
575
|
-
this.$allowlistData = User.DEFAULT_ALLOWLIST_DATA;
|
|
678
|
+
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
679
|
+
this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
680
|
+
this.$allowlistData = [...User.DEFAULT_ALLOWLIST_DATA];
|
|
576
681
|
|
|
577
682
|
if (tilmeld.config.emailUsernames) {
|
|
578
683
|
this.$privateData.push('username');
|
|
@@ -1114,6 +1219,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1114
1219
|
|
|
1115
1220
|
public async $register(data: {
|
|
1116
1221
|
password: string;
|
|
1222
|
+
additionalData?: { [k: string]: any };
|
|
1117
1223
|
}): Promise<{ result: boolean; loggedin: boolean; message: string }> {
|
|
1118
1224
|
const tilmeld = this.$nymph.tilmeld as Tilmeld;
|
|
1119
1225
|
if (!tilmeld.config.allowRegistration) {
|
|
@@ -1130,6 +1236,22 @@ export default class User extends AbleObject<UserData> {
|
|
|
1130
1236
|
message: 'This is already a registered user.',
|
|
1131
1237
|
};
|
|
1132
1238
|
}
|
|
1239
|
+
|
|
1240
|
+
try {
|
|
1241
|
+
for (let callback of (this.constructor as typeof User)
|
|
1242
|
+
.beforeRegisterCallbacks) {
|
|
1243
|
+
if (callback) {
|
|
1244
|
+
await callback(this, data);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
} catch (e: any) {
|
|
1248
|
+
return {
|
|
1249
|
+
result: false,
|
|
1250
|
+
loggedin: false,
|
|
1251
|
+
message: e.message,
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1133
1255
|
if (!('password' in data) || !data.password.length) {
|
|
1134
1256
|
return {
|
|
1135
1257
|
result: false,
|
|
@@ -1158,7 +1280,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
1158
1280
|
|
|
1159
1281
|
// Start transaction.
|
|
1160
1282
|
const transaction = 'tilmeld-register-' + nanoid();
|
|
1283
|
+
const nymph = this.$nymph;
|
|
1161
1284
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1285
|
+
this.$nymph = tnymph;
|
|
1162
1286
|
|
|
1163
1287
|
try {
|
|
1164
1288
|
// Add primary group.
|
|
@@ -1182,6 +1306,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1182
1306
|
}
|
|
1183
1307
|
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
1184
1308
|
await tnymph.rollback(transaction);
|
|
1309
|
+
this.$nymph = nymph;
|
|
1185
1310
|
return {
|
|
1186
1311
|
result: false,
|
|
1187
1312
|
loggedin: false,
|
|
@@ -1282,6 +1407,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1282
1407
|
generatedPrimaryGroup.user = this;
|
|
1283
1408
|
if (!(await generatedPrimaryGroup.$saveSkipAC())) {
|
|
1284
1409
|
await tnymph.rollback(transaction);
|
|
1410
|
+
this.$nymph = nymph;
|
|
1285
1411
|
return {
|
|
1286
1412
|
result: false,
|
|
1287
1413
|
loggedin: false,
|
|
@@ -1316,7 +1442,20 @@ export default class User extends AbleObject<UserData> {
|
|
|
1316
1442
|
message += "You're now registered and logged in!";
|
|
1317
1443
|
loggedin = true;
|
|
1318
1444
|
}
|
|
1445
|
+
|
|
1446
|
+
for (let callback of (this.constructor as typeof User)
|
|
1447
|
+
.afterRegisterCallbacks) {
|
|
1448
|
+
if (callback) {
|
|
1449
|
+
await callback(this, {
|
|
1450
|
+
loggedin,
|
|
1451
|
+
message,
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1319
1456
|
await tnymph.commit(transaction);
|
|
1457
|
+
this.$nymph = nymph;
|
|
1458
|
+
|
|
1320
1459
|
return {
|
|
1321
1460
|
result: true,
|
|
1322
1461
|
loggedin,
|
|
@@ -1324,6 +1463,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1324
1463
|
};
|
|
1325
1464
|
} else {
|
|
1326
1465
|
await tnymph.rollback(transaction);
|
|
1466
|
+
this.$nymph = nymph;
|
|
1327
1467
|
return {
|
|
1328
1468
|
result: false,
|
|
1329
1469
|
loggedin: false,
|
|
@@ -1332,6 +1472,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1332
1472
|
}
|
|
1333
1473
|
} catch (e: any) {
|
|
1334
1474
|
await tnymph.rollback(transaction);
|
|
1475
|
+
this.$nymph = nymph;
|
|
1335
1476
|
throw e;
|
|
1336
1477
|
}
|
|
1337
1478
|
}
|
|
@@ -1532,7 +1673,9 @@ export default class User extends AbleObject<UserData> {
|
|
|
1532
1673
|
|
|
1533
1674
|
// Start transaction.
|
|
1534
1675
|
const transaction = 'tilmeld-save-' + nanoid();
|
|
1676
|
+
const nymph = this.$nymph;
|
|
1535
1677
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1678
|
+
this.$nymph = tnymph;
|
|
1536
1679
|
|
|
1537
1680
|
if (
|
|
1538
1681
|
this.$data.group != null &&
|
|
@@ -1549,6 +1692,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1549
1692
|
await this.$data.group.$saveSkipAC();
|
|
1550
1693
|
} catch (e: any) {
|
|
1551
1694
|
await tnymph.rollback(transaction);
|
|
1695
|
+
this.$nymph = nymph;
|
|
1552
1696
|
throw e;
|
|
1553
1697
|
}
|
|
1554
1698
|
}
|
|
@@ -1562,6 +1706,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1562
1706
|
ret = await super.$save();
|
|
1563
1707
|
} catch (e: any) {
|
|
1564
1708
|
await tnymph.rollback(transaction);
|
|
1709
|
+
this.$nymph = nymph;
|
|
1565
1710
|
throw e;
|
|
1566
1711
|
}
|
|
1567
1712
|
if (ret) {
|
|
@@ -1572,6 +1717,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1572
1717
|
this.guid = preGuid;
|
|
1573
1718
|
this.cdate = preCdate;
|
|
1574
1719
|
this.mdate = preMdate;
|
|
1720
|
+
this.$nymph = nymph;
|
|
1575
1721
|
throw new Error("Couldn't send verification email.");
|
|
1576
1722
|
}
|
|
1577
1723
|
}
|
|
@@ -1587,6 +1733,7 @@ export default class User extends AbleObject<UserData> {
|
|
|
1587
1733
|
} else {
|
|
1588
1734
|
await tnymph.rollback(transaction);
|
|
1589
1735
|
}
|
|
1736
|
+
this.$nymph = nymph;
|
|
1590
1737
|
return ret;
|
|
1591
1738
|
}
|
|
1592
1739
|
|
|
@@ -1624,4 +1771,82 @@ export default class User extends AbleObject<UserData> {
|
|
|
1624
1771
|
}
|
|
1625
1772
|
return await super.$delete();
|
|
1626
1773
|
}
|
|
1774
|
+
|
|
1775
|
+
public static on<T extends EventType>(
|
|
1776
|
+
event: T,
|
|
1777
|
+
callback: T extends 'beforeRegister'
|
|
1778
|
+
? TilmeldBeforeRegisterCallback
|
|
1779
|
+
: T extends 'afterRegister'
|
|
1780
|
+
? TilmeldAfterRegisterCallback
|
|
1781
|
+
: T extends 'beforeLogin'
|
|
1782
|
+
? TilmeldBeforeLoginCallback
|
|
1783
|
+
: T extends 'afterLogin'
|
|
1784
|
+
? TilmeldAfterLoginCallback
|
|
1785
|
+
: T extends 'beforeLogout'
|
|
1786
|
+
? TilmeldBeforeLogoutCallback
|
|
1787
|
+
: T extends 'afterLogout'
|
|
1788
|
+
? TilmeldAfterLogoutCallback
|
|
1789
|
+
: never
|
|
1790
|
+
) {
|
|
1791
|
+
const prop = (event + 'Callbacks') as T extends 'beforeRegister'
|
|
1792
|
+
? 'beforeRegisterCallbacks'
|
|
1793
|
+
: T extends 'afterRegister'
|
|
1794
|
+
? 'afterRegisterCallbacks'
|
|
1795
|
+
: T extends 'beforeLogin'
|
|
1796
|
+
? 'beforeLoginCallbacks'
|
|
1797
|
+
: T extends 'afterLogin'
|
|
1798
|
+
? 'afterLoginCallbacks'
|
|
1799
|
+
: T extends 'beforeLogout'
|
|
1800
|
+
? 'beforeLogoutCallbacks'
|
|
1801
|
+
: T extends 'afterLogout'
|
|
1802
|
+
? 'afterLogoutCallbacks'
|
|
1803
|
+
: never;
|
|
1804
|
+
if (!(prop in this)) {
|
|
1805
|
+
throw new Error('Invalid event type.');
|
|
1806
|
+
}
|
|
1807
|
+
// @ts-ignore: The callback should always be the right type here.
|
|
1808
|
+
this[prop].push(callback);
|
|
1809
|
+
return () => this.off(event, callback);
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
public static off<T extends EventType>(
|
|
1813
|
+
event: T,
|
|
1814
|
+
callback: T extends 'beforeRegister'
|
|
1815
|
+
? TilmeldBeforeRegisterCallback
|
|
1816
|
+
: T extends 'afterRegister'
|
|
1817
|
+
? TilmeldAfterRegisterCallback
|
|
1818
|
+
: T extends 'beforeLogin'
|
|
1819
|
+
? TilmeldBeforeLoginCallback
|
|
1820
|
+
: T extends 'afterLogin'
|
|
1821
|
+
? TilmeldAfterLoginCallback
|
|
1822
|
+
: T extends 'beforeLogout'
|
|
1823
|
+
? TilmeldBeforeLogoutCallback
|
|
1824
|
+
: T extends 'afterLogout'
|
|
1825
|
+
? TilmeldAfterLogoutCallback
|
|
1826
|
+
: never
|
|
1827
|
+
) {
|
|
1828
|
+
const prop = (event + 'Callbacks') as T extends 'beforeRegister'
|
|
1829
|
+
? 'beforeRegisterCallbacks'
|
|
1830
|
+
: T extends 'afterRegister'
|
|
1831
|
+
? 'afterRegisterCallbacks'
|
|
1832
|
+
: T extends 'beforeLogin'
|
|
1833
|
+
? 'beforeLoginCallbacks'
|
|
1834
|
+
: T extends 'afterLogin'
|
|
1835
|
+
? 'afterLoginCallbacks'
|
|
1836
|
+
: T extends 'beforeLogout'
|
|
1837
|
+
? 'beforeLogoutCallbacks'
|
|
1838
|
+
: T extends 'afterLogout'
|
|
1839
|
+
? 'afterLogoutCallbacks'
|
|
1840
|
+
: never;
|
|
1841
|
+
if (!(prop in this)) {
|
|
1842
|
+
return false;
|
|
1843
|
+
}
|
|
1844
|
+
// @ts-ignore: The callback should always be the right type here.
|
|
1845
|
+
const i = this[prop].indexOf(callback);
|
|
1846
|
+
if (i > -1) {
|
|
1847
|
+
// @ts-ignore: The callback should always be the right type here.
|
|
1848
|
+
this[prop].splice(i, 1);
|
|
1849
|
+
}
|
|
1850
|
+
return true;
|
|
1851
|
+
}
|
|
1627
1852
|
}
|
package/src/conf/d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EmailOptions } from 'email-templates';
|
|
2
|
+
|
|
2
3
|
import type Tilmeld from '../Tilmeld';
|
|
3
4
|
import Group, { GroupData } from '../Group';
|
|
4
5
|
import User, { UserData } from '../User';
|
|
@@ -64,6 +65,35 @@ export interface Config {
|
|
|
64
65
|
* a concern. Same risks as user search if generatePrimary is true.)
|
|
65
66
|
*/
|
|
66
67
|
enableGroupSearch: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* A list of UIDs that can be read from the client by anyone. (getUID)
|
|
70
|
+
*
|
|
71
|
+
* Note: If you'd like to limit the access to logged in users, give them an
|
|
72
|
+
* ability like "uid/get/nameofuid".
|
|
73
|
+
*/
|
|
74
|
+
clientReadableUIDs: string[];
|
|
75
|
+
/**
|
|
76
|
+
* A list of UIDs that can be created from the client by anyone. (newUID)
|
|
77
|
+
*
|
|
78
|
+
* Inclusion in this list implies inclusion in clientReadableUIDs.
|
|
79
|
+
*
|
|
80
|
+
* Note: If you'd like to limit the access to logged in users, give them an
|
|
81
|
+
* ability like "uid/new/nameofuid".
|
|
82
|
+
*/
|
|
83
|
+
clientEnabledUIDs: string[];
|
|
84
|
+
/**
|
|
85
|
+
* A list of UIDs that can be set from the client by anyone. (setUID,
|
|
86
|
+
* renameUID)
|
|
87
|
+
*
|
|
88
|
+
* Inclusion in this list implies inclusion in clientReadableUIDs and
|
|
89
|
+
* clientEnabledUIDs.
|
|
90
|
+
*
|
|
91
|
+
* Note: There is no way to run renameUID from the client.
|
|
92
|
+
*
|
|
93
|
+
* Note: If you'd like to limit the access to logged in users, give them an
|
|
94
|
+
* ability like "uid/set/nameofuid".
|
|
95
|
+
*/
|
|
96
|
+
clientSetabledUIDs: string[];
|
|
67
97
|
/**
|
|
68
98
|
* These will be the available fields for users. (Some fields, like username,
|
|
69
99
|
* can't be excluded.)
|
package/src/conf/defaults.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nymphJoiProps } from '@nymphjs/nymph';
|
|
1
2
|
import path from 'path';
|
|
2
3
|
import jwt from 'jsonwebtoken';
|
|
3
4
|
import { nanoid } from 'nanoid';
|
|
@@ -20,6 +21,9 @@ export default {
|
|
|
20
21
|
allowUsernameChange: true,
|
|
21
22
|
enableUserSearch: false,
|
|
22
23
|
enableGroupSearch: false,
|
|
24
|
+
clientReadableUIDs: [],
|
|
25
|
+
clientEnabledUIDs: [],
|
|
26
|
+
clientSetabledUIDs: [],
|
|
23
27
|
userFields: ['name', 'email', 'phone'],
|
|
24
28
|
regFields: ['name', 'email'],
|
|
25
29
|
verifyEmail: true,
|
|
@@ -154,29 +158,8 @@ export default {
|
|
|
154
158
|
Joi.attempt(
|
|
155
159
|
group.$getValidatable(),
|
|
156
160
|
Joi.object().keys({
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Joi.any().only().allow(null),
|
|
160
|
-
Joi.string().trim(false).length(24).hex()
|
|
161
|
-
)
|
|
162
|
-
.required(),
|
|
163
|
-
cdate: Joi.alternatives()
|
|
164
|
-
.try(Joi.any().only().allow(null), Joi.number())
|
|
165
|
-
.required(),
|
|
166
|
-
mdate: Joi.alternatives()
|
|
167
|
-
.try(Joi.any().only().allow(null), Joi.number())
|
|
168
|
-
.required(),
|
|
169
|
-
tags: Joi.array()
|
|
170
|
-
.items(
|
|
171
|
-
Joi.string()
|
|
172
|
-
.pattern(/[\x01-\x1F\x7F]/, {
|
|
173
|
-
name: 'control characters',
|
|
174
|
-
invert: true,
|
|
175
|
-
})
|
|
176
|
-
.min(1)
|
|
177
|
-
)
|
|
178
|
-
.required(),
|
|
179
|
-
groupname: Joi.string().trim(false).min(1).required(),
|
|
161
|
+
...nymphJoiProps,
|
|
162
|
+
groupname: Joi.string().trim(false).required(),
|
|
180
163
|
enabled: Joi.boolean().required(),
|
|
181
164
|
email: Joi.string()
|
|
182
165
|
.trim(false)
|
|
@@ -188,7 +171,6 @@ export default {
|
|
|
188
171
|
name: 'control characters',
|
|
189
172
|
invert: true,
|
|
190
173
|
})
|
|
191
|
-
.min(1)
|
|
192
174
|
.max(512)
|
|
193
175
|
.required(),
|
|
194
176
|
avatar: Joi.string()
|
|
@@ -198,7 +180,6 @@ export default {
|
|
|
198
180
|
name: 'control characters',
|
|
199
181
|
invert: true,
|
|
200
182
|
})
|
|
201
|
-
.min(1)
|
|
202
183
|
.max(1024),
|
|
203
184
|
phone: Joi.string()
|
|
204
185
|
.trim(false)
|
|
@@ -211,7 +192,6 @@ export default {
|
|
|
211
192
|
name: 'control characters',
|
|
212
193
|
invert: true,
|
|
213
194
|
})
|
|
214
|
-
.min(1)
|
|
215
195
|
.max(256)
|
|
216
196
|
),
|
|
217
197
|
defaultPrimary: Joi.boolean(),
|
|
@@ -225,29 +205,8 @@ export default {
|
|
|
225
205
|
Joi.attempt(
|
|
226
206
|
user.$getValidatable(),
|
|
227
207
|
Joi.object().keys({
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
Joi.any().only().allow(null),
|
|
231
|
-
Joi.string().trim(false).length(24).hex()
|
|
232
|
-
)
|
|
233
|
-
.required(),
|
|
234
|
-
cdate: Joi.alternatives()
|
|
235
|
-
.try(Joi.any().only().allow(null), Joi.number())
|
|
236
|
-
.required(),
|
|
237
|
-
mdate: Joi.alternatives()
|
|
238
|
-
.try(Joi.any().only().allow(null), Joi.number())
|
|
239
|
-
.required(),
|
|
240
|
-
tags: Joi.array()
|
|
241
|
-
.items(
|
|
242
|
-
Joi.string()
|
|
243
|
-
.pattern(/[\x01-\x1F\x7F]/, {
|
|
244
|
-
name: 'control characters',
|
|
245
|
-
invert: true,
|
|
246
|
-
})
|
|
247
|
-
.min(1)
|
|
248
|
-
)
|
|
249
|
-
.required(),
|
|
250
|
-
username: Joi.string().trim(false).min(1).required(),
|
|
208
|
+
...nymphJoiProps,
|
|
209
|
+
username: Joi.string().trim(false).required(),
|
|
251
210
|
enabled: Joi.boolean().required(),
|
|
252
211
|
email: Joi.string()
|
|
253
212
|
.trim(false)
|
|
@@ -259,7 +218,6 @@ export default {
|
|
|
259
218
|
name: 'control characters',
|
|
260
219
|
invert: true,
|
|
261
220
|
})
|
|
262
|
-
.min(1)
|
|
263
221
|
.max(512)
|
|
264
222
|
.required(),
|
|
265
223
|
nameMiddle: Joi.string()
|
|
@@ -268,7 +226,6 @@ export default {
|
|
|
268
226
|
name: 'control characters',
|
|
269
227
|
invert: true,
|
|
270
228
|
})
|
|
271
|
-
.min(1)
|
|
272
229
|
.max(512),
|
|
273
230
|
nameLast: Joi.string()
|
|
274
231
|
.trim(false)
|
|
@@ -276,7 +233,6 @@ export default {
|
|
|
276
233
|
name: 'control characters',
|
|
277
234
|
invert: true,
|
|
278
235
|
})
|
|
279
|
-
.min(1)
|
|
280
236
|
.max(512),
|
|
281
237
|
name: Joi.string()
|
|
282
238
|
.trim(false)
|
|
@@ -284,7 +240,6 @@ export default {
|
|
|
284
240
|
name: 'control characters',
|
|
285
241
|
invert: true,
|
|
286
242
|
})
|
|
287
|
-
.min(1)
|
|
288
243
|
.max(512)
|
|
289
244
|
.required(),
|
|
290
245
|
avatar: Joi.string()
|
|
@@ -294,7 +249,6 @@ export default {
|
|
|
294
249
|
name: 'control characters',
|
|
295
250
|
invert: true,
|
|
296
251
|
})
|
|
297
|
-
.min(1)
|
|
298
252
|
.max(1024),
|
|
299
253
|
phone: Joi.string()
|
|
300
254
|
.trim(false)
|
|
@@ -307,7 +261,6 @@ export default {
|
|
|
307
261
|
name: 'control characters',
|
|
308
262
|
invert: true,
|
|
309
263
|
})
|
|
310
|
-
.min(1)
|
|
311
264
|
.max(256)
|
|
312
265
|
),
|
|
313
266
|
inheritAbilities: Joi.boolean(),
|
|
@@ -347,8 +300,8 @@ export default {
|
|
|
347
300
|
})
|
|
348
301
|
.length(10),
|
|
349
302
|
recoverSecretDate: Joi.number(),
|
|
350
|
-
salt: Joi.string().trim(false)
|
|
351
|
-
password: Joi.string().trim(false).
|
|
303
|
+
salt: Joi.string().trim(false),
|
|
304
|
+
password: Joi.string().trim(false).required(),
|
|
352
305
|
}),
|
|
353
306
|
'Invalid User: '
|
|
354
307
|
);
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TilmeldAccessLevels } from '@nymphjs/nymph';
|
|
2
|
+
import Joi from 'joi';
|
|
3
|
+
|
|
4
|
+
import User from './User';
|
|
5
|
+
import Group from './Group';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
user: Joi.object().instance(User),
|
|
9
|
+
group: Joi.object().instance(Group),
|
|
10
|
+
acUser: Joi.number().valid(
|
|
11
|
+
TilmeldAccessLevels.NO_ACCESS,
|
|
12
|
+
TilmeldAccessLevels.READ_ACCESS,
|
|
13
|
+
TilmeldAccessLevels.WRITE_ACCESS,
|
|
14
|
+
TilmeldAccessLevels.FULL_ACCESS
|
|
15
|
+
),
|
|
16
|
+
acGroup: Joi.number().valid(
|
|
17
|
+
TilmeldAccessLevels.NO_ACCESS,
|
|
18
|
+
TilmeldAccessLevels.READ_ACCESS,
|
|
19
|
+
TilmeldAccessLevels.WRITE_ACCESS,
|
|
20
|
+
TilmeldAccessLevels.FULL_ACCESS
|
|
21
|
+
),
|
|
22
|
+
acOther: Joi.number().valid(
|
|
23
|
+
TilmeldAccessLevels.NO_ACCESS,
|
|
24
|
+
TilmeldAccessLevels.READ_ACCESS,
|
|
25
|
+
TilmeldAccessLevels.WRITE_ACCESS,
|
|
26
|
+
TilmeldAccessLevels.FULL_ACCESS
|
|
27
|
+
),
|
|
28
|
+
acRead: Joi.array().items(
|
|
29
|
+
Joi.alternatives().try(
|
|
30
|
+
Joi.object().instance(User),
|
|
31
|
+
Joi.object().instance(Group)
|
|
32
|
+
)
|
|
33
|
+
),
|
|
34
|
+
acWrite: Joi.array().items(
|
|
35
|
+
Joi.alternatives().try(
|
|
36
|
+
Joi.object().instance(User),
|
|
37
|
+
Joi.object().instance(Group)
|
|
38
|
+
)
|
|
39
|
+
),
|
|
40
|
+
acFull: Joi.array().items(
|
|
41
|
+
Joi.alternatives().try(
|
|
42
|
+
Joi.object().instance(User),
|
|
43
|
+
Joi.object().instance(Group)
|
|
44
|
+
)
|
|
45
|
+
),
|
|
46
|
+
};
|