@nymphjs/tilmeld 1.0.0-beta.4 → 1.0.0-beta.41
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 +189 -0
- package/README.md +13 -0
- package/dist/Group.d.ts +4 -7
- package/dist/Group.js +107 -83
- package/dist/Group.js.map +1 -1
- package/dist/Tilmeld.d.ts +10 -9
- package/dist/Tilmeld.js +226 -175
- package/dist/Tilmeld.js.map +1 -1
- package/dist/User.d.ts +66 -13
- package/dist/User.js +421 -128
- 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 +24 -21
- package/src/Group.ts +140 -102
- package/src/Tilmeld.ts +312 -221
- package/src/User.ts +600 -145
- 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/typedoc.json +4 -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 {
|
|
@@ -30,32 +33,32 @@ class User extends AbleObject_1.default {
|
|
|
30
33
|
}
|
|
31
34
|
return entity;
|
|
32
35
|
}
|
|
33
|
-
static factorySync(
|
|
34
|
-
return super.factorySync(
|
|
36
|
+
static factorySync() {
|
|
37
|
+
return super.factorySync();
|
|
35
38
|
}
|
|
36
|
-
constructor(
|
|
37
|
-
super(
|
|
39
|
+
constructor() {
|
|
40
|
+
super();
|
|
38
41
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
39
42
|
this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
40
43
|
this.$allowlistData = [...User.DEFAULT_ALLOWLIST_DATA];
|
|
41
44
|
this.$allowlistTags = [];
|
|
42
45
|
this.$skipAcWhenSaving = false;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.$updateDataProtection();
|
|
49
|
-
}
|
|
46
|
+
this.$data.enabled = true;
|
|
47
|
+
this.$data.abilities = [];
|
|
48
|
+
this.$data.groups = [];
|
|
49
|
+
this.$data.inheritAbilities = true;
|
|
50
|
+
this.$updateDataProtection();
|
|
50
51
|
}
|
|
51
52
|
static current(returnObjectIfNotExist) {
|
|
52
|
-
|
|
53
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
54
|
+
if (tilmeld.currentUser == null) {
|
|
53
55
|
return returnObjectIfNotExist ? this.factorySync() : null;
|
|
54
56
|
}
|
|
55
|
-
return
|
|
57
|
+
return tilmeld.currentUser;
|
|
56
58
|
}
|
|
57
59
|
static async sendRecovery(data) {
|
|
58
|
-
|
|
60
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
61
|
+
if (!tilmeld.config.pwRecovery) {
|
|
59
62
|
return {
|
|
60
63
|
result: false,
|
|
61
64
|
message: 'Account recovery is not allowed.',
|
|
@@ -63,9 +66,8 @@ class User extends AbleObject_1.default {
|
|
|
63
66
|
}
|
|
64
67
|
let user;
|
|
65
68
|
const options = {};
|
|
66
|
-
if (!
|
|
67
|
-
|
|
68
|
-
const getUser = await this.nymph.getEntity({ class: this.tilmeld.User, skipAc: true }, {
|
|
69
|
+
if (!tilmeld.config.emailUsernames && data.recoveryType === 'username') {
|
|
70
|
+
const getUser = await this.nymph.getEntity({ class: tilmeld.User, skipAc: true }, {
|
|
69
71
|
type: '&',
|
|
70
72
|
ilike: ['email', data.account.replace(/([\\%_])/g, (s) => `\\${s}`)],
|
|
71
73
|
});
|
|
@@ -86,7 +88,7 @@ class User extends AbleObject_1.default {
|
|
|
86
88
|
options.locals = {};
|
|
87
89
|
}
|
|
88
90
|
else if (data.recoveryType === 'password') {
|
|
89
|
-
const getUser = await
|
|
91
|
+
const getUser = await tilmeld.User.factoryUsername(data.account);
|
|
90
92
|
if (getUser.guid == null) {
|
|
91
93
|
return {
|
|
92
94
|
result: false,
|
|
@@ -108,13 +110,13 @@ class User extends AbleObject_1.default {
|
|
|
108
110
|
};
|
|
109
111
|
options.locals = {
|
|
110
112
|
recoverCode: getUser.recoverSecret,
|
|
111
|
-
timeLimit:
|
|
113
|
+
timeLimit: tilmeld.config.pwRecoveryTimeLimit,
|
|
112
114
|
};
|
|
113
115
|
}
|
|
114
116
|
else {
|
|
115
117
|
return { result: false, message: 'Invalid recovery type.' };
|
|
116
118
|
}
|
|
117
|
-
if (await
|
|
119
|
+
if (await tilmeld.config.sendEmail(tilmeld, options, user)) {
|
|
118
120
|
return {
|
|
119
121
|
result: true,
|
|
120
122
|
message: "We've sent an email to your registered address. Please " +
|
|
@@ -126,17 +128,18 @@ class User extends AbleObject_1.default {
|
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
static async recover(data) {
|
|
129
|
-
|
|
131
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
132
|
+
if (!tilmeld.config.pwRecovery) {
|
|
130
133
|
return {
|
|
131
134
|
result: false,
|
|
132
135
|
message: 'Account recovery is not allowed.',
|
|
133
136
|
};
|
|
134
137
|
}
|
|
135
|
-
const user = await
|
|
138
|
+
const user = await tilmeld.User.factoryUsername(data.username);
|
|
136
139
|
if (user.guid == null ||
|
|
137
140
|
user.recoverSecret == null ||
|
|
138
141
|
data.secret !== user.recoverSecret ||
|
|
139
|
-
(0, strtotime_1.default)('+' +
|
|
142
|
+
(0, strtotime_1.default)('+' + tilmeld.config.pwRecoveryTimeLimit, Math.floor((user.recoverSecretDate ?? 0) / 1000)) *
|
|
140
143
|
1000 <
|
|
141
144
|
Date.now()) {
|
|
142
145
|
return {
|
|
@@ -161,22 +164,24 @@ class User extends AbleObject_1.default {
|
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
static getClientConfig() {
|
|
167
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
164
168
|
return {
|
|
165
|
-
regFields:
|
|
166
|
-
userFields:
|
|
167
|
-
emailUsernames:
|
|
168
|
-
allowRegistration:
|
|
169
|
-
allowUsernameChange:
|
|
170
|
-
pwRecovery:
|
|
171
|
-
verifyEmail:
|
|
172
|
-
unverifiedAccess:
|
|
169
|
+
regFields: tilmeld.config.regFields,
|
|
170
|
+
userFields: tilmeld.config.userFields,
|
|
171
|
+
emailUsernames: tilmeld.config.emailUsernames,
|
|
172
|
+
allowRegistration: tilmeld.config.allowRegistration,
|
|
173
|
+
allowUsernameChange: tilmeld.config.allowUsernameChange,
|
|
174
|
+
pwRecovery: tilmeld.config.pwRecovery,
|
|
175
|
+
verifyEmail: tilmeld.config.verifyEmail,
|
|
176
|
+
unverifiedAccess: tilmeld.config.unverifiedAccess,
|
|
173
177
|
};
|
|
174
178
|
}
|
|
175
179
|
static async loginUser(data) {
|
|
180
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
176
181
|
if (!('username' in data) || !data.username.length) {
|
|
177
182
|
return { result: false, message: 'Incorrect login/password.' };
|
|
178
183
|
}
|
|
179
|
-
const user = await
|
|
184
|
+
const user = await tilmeld.User.factoryUsername(data.username);
|
|
180
185
|
const result = await user.$login(data);
|
|
181
186
|
if (result.result) {
|
|
182
187
|
user.$updateDataProtection();
|
|
@@ -185,19 +190,33 @@ class User extends AbleObject_1.default {
|
|
|
185
190
|
return result;
|
|
186
191
|
}
|
|
187
192
|
async $login(data) {
|
|
188
|
-
const tilmeld = this
|
|
193
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
189
194
|
if (this.guid == null) {
|
|
190
195
|
return { result: false, message: 'Incorrect login/password.' };
|
|
191
196
|
}
|
|
192
197
|
if (!this.$data.enabled) {
|
|
193
198
|
return { result: false, message: 'This user is disabled.' };
|
|
194
199
|
}
|
|
195
|
-
if (this.$gatekeeper()) {
|
|
200
|
+
if (await this.$gatekeeper()) {
|
|
196
201
|
return { result: true, message: 'You are already logged in.' };
|
|
197
202
|
}
|
|
198
203
|
if (!this.$checkPassword(data.password)) {
|
|
199
204
|
return { result: false, message: 'Incorrect login/password.' };
|
|
200
205
|
}
|
|
206
|
+
if (this.$data.totpSecret != null) {
|
|
207
|
+
if (data.code == null ||
|
|
208
|
+
typeof data.code !== 'string' ||
|
|
209
|
+
data.code.length !== 6) {
|
|
210
|
+
return {
|
|
211
|
+
result: false,
|
|
212
|
+
needTOTP: true,
|
|
213
|
+
message: 'You need to provide a 2FA code.',
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (!this.$checkTOTPCode(data.code)) {
|
|
217
|
+
return { result: false, message: 'Incorrect 2FA code.' };
|
|
218
|
+
}
|
|
219
|
+
}
|
|
201
220
|
try {
|
|
202
221
|
for (let callback of this.constructor
|
|
203
222
|
.beforeLoginCallbacks) {
|
|
@@ -223,8 +242,63 @@ class User extends AbleObject_1.default {
|
|
|
223
242
|
}
|
|
224
243
|
return { result: true, message: 'You are logged in.' };
|
|
225
244
|
}
|
|
245
|
+
async $switchUser(data) {
|
|
246
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
247
|
+
if (this.guid == null) {
|
|
248
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
249
|
+
}
|
|
250
|
+
let user = tilmeld.User.current();
|
|
251
|
+
if (!user || user.guid == null) {
|
|
252
|
+
return { result: false, message: "You're not logged in." };
|
|
253
|
+
}
|
|
254
|
+
const isCurrentUser = user != null && user.$is(this);
|
|
255
|
+
if (isCurrentUser) {
|
|
256
|
+
return { result: false, message: "You can't switch to yourself." };
|
|
257
|
+
}
|
|
258
|
+
const toAbilities = this.$data.abilities || [];
|
|
259
|
+
const fromAbilities = user.abilities || [];
|
|
260
|
+
if (fromAbilities.indexOf('tilmeld/switch') === -1 &&
|
|
261
|
+
fromAbilities.indexOf('system/admin') === -1) {
|
|
262
|
+
return {
|
|
263
|
+
result: false,
|
|
264
|
+
message: "You don't have permission to switch users.",
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (toAbilities.indexOf('system/admin') !== -1 ||
|
|
268
|
+
toAbilities.indexOf('tilmeld/admin') !== -1) {
|
|
269
|
+
return { result: false, message: "You can't switch to an admin." };
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
for (let callback of this.constructor
|
|
273
|
+
.beforeLoginCallbacks) {
|
|
274
|
+
if (callback) {
|
|
275
|
+
await callback(this, {
|
|
276
|
+
username: this.$data.username || '',
|
|
277
|
+
password: '',
|
|
278
|
+
...(data || {}),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch (e) {
|
|
284
|
+
return {
|
|
285
|
+
result: false,
|
|
286
|
+
message: e.message,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
if (!tilmeld.loginSwitch(this, true)) {
|
|
290
|
+
return { result: false, message: 'Incorrect login/password.' };
|
|
291
|
+
}
|
|
292
|
+
for (let callback of this.constructor
|
|
293
|
+
.afterLoginCallbacks) {
|
|
294
|
+
if (callback) {
|
|
295
|
+
await callback(this);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return { result: true, message: 'You are logged in.' };
|
|
299
|
+
}
|
|
226
300
|
async $logout() {
|
|
227
|
-
const tilmeld = this
|
|
301
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
228
302
|
try {
|
|
229
303
|
for (let callback of this.constructor
|
|
230
304
|
.beforeLogoutCallbacks) {
|
|
@@ -239,7 +313,7 @@ class User extends AbleObject_1.default {
|
|
|
239
313
|
message: e.message,
|
|
240
314
|
};
|
|
241
315
|
}
|
|
242
|
-
tilmeld.logout();
|
|
316
|
+
await tilmeld.logout();
|
|
243
317
|
for (let callback of this.constructor
|
|
244
318
|
.afterLogoutCallbacks) {
|
|
245
319
|
if (callback) {
|
|
@@ -259,50 +333,84 @@ class User extends AbleObject_1.default {
|
|
|
259
333
|
(0, md5_1.default)(this.$data.email.trim().toLowerCase()).toString() +
|
|
260
334
|
'?d=identicon&s=40');
|
|
261
335
|
}
|
|
336
|
+
$getGid() {
|
|
337
|
+
if (this.$data.group) {
|
|
338
|
+
return this.$data.group.guid;
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
$getGids() {
|
|
343
|
+
if (this.$data.groups) {
|
|
344
|
+
return this.$data.groups
|
|
345
|
+
.map((group) => group.guid)
|
|
346
|
+
.filter((guid) => guid != null);
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
262
350
|
async $getDescendantGroups() {
|
|
263
351
|
if (this.$descendantGroups == null) {
|
|
264
352
|
this.$descendantGroups = [];
|
|
265
353
|
if (this.$data.group != null) {
|
|
354
|
+
await this.$data.group.$wake();
|
|
266
355
|
this.$descendantGroups = await this.$data.group.$getDescendants();
|
|
267
356
|
}
|
|
357
|
+
await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
|
|
268
358
|
for (let curGroup of this.$data.groups ?? []) {
|
|
269
359
|
this.$descendantGroups = this.$descendantGroups?.concat(await curGroup.$getDescendants());
|
|
270
360
|
}
|
|
271
361
|
}
|
|
272
362
|
return this.$descendantGroups;
|
|
273
363
|
}
|
|
274
|
-
$getDescendantGroupsSync() {
|
|
275
|
-
if (this.$descendantGroups == null) {
|
|
276
|
-
this.$descendantGroups = [];
|
|
277
|
-
if (this.$data.group != null) {
|
|
278
|
-
this.$descendantGroups = this.$data.group.$getDescendantsSync();
|
|
279
|
-
}
|
|
280
|
-
for (let curGroup of this.$data.groups ?? []) {
|
|
281
|
-
this.$descendantGroups = this.$descendantGroups?.concat(curGroup.$getDescendantsSync());
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return this.$descendantGroups;
|
|
285
|
-
}
|
|
286
364
|
$jsonAcceptData(input, allowConflict = false) {
|
|
287
|
-
const tilmeld = this
|
|
288
|
-
this.$
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
!tilmeld.
|
|
293
|
-
|
|
365
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
366
|
+
this.$check();
|
|
367
|
+
if ('abilities' in input.data &&
|
|
368
|
+
input.data.abilities?.includes('system/admin') !==
|
|
369
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
370
|
+
(!tilmeld.currentUser ||
|
|
371
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
372
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke system/admin.");
|
|
373
|
+
}
|
|
374
|
+
if ('abilities' in input.data &&
|
|
375
|
+
input.data.abilities?.includes('tilmeld/admin') !==
|
|
376
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
377
|
+
(!tilmeld.currentUser ||
|
|
378
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
379
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/admin.");
|
|
380
|
+
}
|
|
381
|
+
if ('abilities' in input.data &&
|
|
382
|
+
input.data.abilities?.includes('tilmeld/switch') !==
|
|
383
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
384
|
+
(!tilmeld.currentUser ||
|
|
385
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
386
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/switch.");
|
|
294
387
|
}
|
|
295
388
|
this.$originalEmail = this.$data.email;
|
|
296
389
|
super.$jsonAcceptData(input, allowConflict);
|
|
297
390
|
}
|
|
298
391
|
$jsonAcceptPatch(patch, allowConflict = false) {
|
|
299
|
-
const tilmeld = this
|
|
300
|
-
this.$
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
!tilmeld.
|
|
305
|
-
|
|
392
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
393
|
+
this.$check();
|
|
394
|
+
if ('abilities' in patch.set &&
|
|
395
|
+
patch.set.abilities?.includes('system/admin') !==
|
|
396
|
+
this.$data.abilities?.includes('system/admin') &&
|
|
397
|
+
(!tilmeld.currentUser ||
|
|
398
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
399
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke system/admin.");
|
|
400
|
+
}
|
|
401
|
+
if ('abilities' in patch.set &&
|
|
402
|
+
patch.set.abilities?.includes('tilmeld/admin') !==
|
|
403
|
+
this.$data.abilities?.includes('tilmeld/admin') &&
|
|
404
|
+
(!tilmeld.currentUser ||
|
|
405
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
406
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/admin.");
|
|
407
|
+
}
|
|
408
|
+
if ('abilities' in patch.set &&
|
|
409
|
+
patch.set.abilities?.includes('tilmeld/switch') !==
|
|
410
|
+
this.$data.abilities?.includes('tilmeld/switch') &&
|
|
411
|
+
(!tilmeld.currentUser ||
|
|
412
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) {
|
|
413
|
+
throw new errors_1.BadDataError("You don't have the authority to grant or revoke tilmeld/switch.");
|
|
306
414
|
}
|
|
307
415
|
this.$originalEmail = this.$data.email;
|
|
308
416
|
super.$jsonAcceptPatch(patch, allowConflict);
|
|
@@ -312,7 +420,7 @@ class User extends AbleObject_1.default {
|
|
|
312
420
|
this.$updateDataProtection();
|
|
313
421
|
}
|
|
314
422
|
$updateDataProtection(givenUser) {
|
|
315
|
-
const tilmeld = this
|
|
423
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
316
424
|
let user = givenUser ?? tilmeld.User.current();
|
|
317
425
|
this.$clientEnabledMethods = [...User.DEFAULT_CLIENT_ENABLED_METHODS];
|
|
318
426
|
this.$privateData = [...User.DEFAULT_PRIVATE_DATA];
|
|
@@ -328,13 +436,18 @@ class User extends AbleObject_1.default {
|
|
|
328
436
|
if (isCurrentUser) {
|
|
329
437
|
this.$clientEnabledMethods.push('$gatekeeper');
|
|
330
438
|
this.$clientEnabledMethods.push('$changePassword');
|
|
439
|
+
this.$clientEnabledMethods.push('$revokeCurrentTokens');
|
|
331
440
|
this.$clientEnabledMethods.push('$logout');
|
|
332
441
|
this.$clientEnabledMethods.push('$sendEmailVerification');
|
|
442
|
+
this.$clientEnabledMethods.push('$hasTOTPSecret');
|
|
443
|
+
this.$clientEnabledMethods.push('$getNewTOTPSecret');
|
|
444
|
+
this.$clientEnabledMethods.push('$saveTOTPSecret');
|
|
445
|
+
this.$clientEnabledMethods.push('$removeTOTPSecret');
|
|
333
446
|
}
|
|
334
447
|
if (user != null &&
|
|
335
448
|
(abilities.indexOf('tilmeld/admin') !== -1 ||
|
|
336
449
|
abilities.indexOf('system/admin') !== -1)) {
|
|
337
|
-
this.$privateData = ['password', 'salt'];
|
|
450
|
+
this.$privateData = ['password', 'salt', 'totpSecret'];
|
|
338
451
|
this.$allowlistData = undefined;
|
|
339
452
|
}
|
|
340
453
|
else if (isCurrentUser || isNewUser) {
|
|
@@ -355,41 +468,61 @@ class User extends AbleObject_1.default {
|
|
|
355
468
|
this.$allowlistData.push('phone');
|
|
356
469
|
}
|
|
357
470
|
this.$privateData = [
|
|
471
|
+
'enabled',
|
|
358
472
|
'secret',
|
|
473
|
+
'emailChangeDate',
|
|
359
474
|
'newEmailSecret',
|
|
360
|
-
'cancelEmailAddress',
|
|
361
475
|
'cancelEmailSecret',
|
|
362
|
-
'
|
|
476
|
+
'cancelEmailAddress',
|
|
363
477
|
'recoverSecret',
|
|
364
478
|
'recoverSecretDate',
|
|
365
|
-
'password',
|
|
366
479
|
'salt',
|
|
480
|
+
'password',
|
|
481
|
+
'passwordTemp',
|
|
482
|
+
'totpSecret',
|
|
367
483
|
];
|
|
368
484
|
}
|
|
485
|
+
if (user != null &&
|
|
486
|
+
!isCurrentUser &&
|
|
487
|
+
(abilities.indexOf('tilmeld/switch') !== -1 ||
|
|
488
|
+
abilities.indexOf('system/admin') !== -1)) {
|
|
489
|
+
this.$clientEnabledMethods.push('$switchUser');
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
$updateGroupDataProtection() {
|
|
493
|
+
if (this.$data.group != null && !this.$data.group.$asleep()) {
|
|
494
|
+
this.$data.group.$updateDataProtection();
|
|
495
|
+
}
|
|
496
|
+
for (let group of this.$data.groups ?? []) {
|
|
497
|
+
if (!group.$asleep()) {
|
|
498
|
+
group.$updateDataProtection();
|
|
499
|
+
}
|
|
500
|
+
}
|
|
369
501
|
}
|
|
370
|
-
$gatekeeper(ability) {
|
|
371
|
-
const tilmeld = this
|
|
502
|
+
async $gatekeeper(ability) {
|
|
503
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
372
504
|
if (ability == null) {
|
|
373
505
|
return tilmeld.User.current()?.$is(this) ?? false;
|
|
374
506
|
}
|
|
375
507
|
if (this.$gatekeeperCache == null) {
|
|
376
508
|
let abilities = this.$data.abilities ?? [];
|
|
377
509
|
if (this.$data.inheritAbilities) {
|
|
510
|
+
await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
|
|
378
511
|
for (let curGroup of this.$data.groups ?? []) {
|
|
379
512
|
if (curGroup.enabled) {
|
|
380
513
|
abilities = abilities.concat(curGroup.abilities ?? []);
|
|
381
514
|
}
|
|
382
515
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
abilities = abilities.concat(
|
|
516
|
+
await this.$data.group?.$wake();
|
|
517
|
+
const group = this.$data.group;
|
|
518
|
+
if (group != null && group.cdate != null && group.enabled) {
|
|
519
|
+
abilities = abilities.concat(group.abilities ?? []);
|
|
387
520
|
}
|
|
388
521
|
}
|
|
389
522
|
this.$gatekeeperCache = Object.fromEntries(abilities.map((ability) => [ability, true]));
|
|
390
523
|
}
|
|
391
524
|
return ((ability in this.$gatekeeperCache && !!this.$gatekeeperCache[ability]) ||
|
|
392
|
-
!!this.$
|
|
525
|
+
!!this.$data.abilities?.includes('system/admin'));
|
|
393
526
|
}
|
|
394
527
|
$clearCache() {
|
|
395
528
|
const ret = super.$clearCache();
|
|
@@ -398,7 +531,7 @@ class User extends AbleObject_1.default {
|
|
|
398
531
|
return ret;
|
|
399
532
|
}
|
|
400
533
|
async $sendEmailVerification() {
|
|
401
|
-
const tilmeld = this
|
|
534
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
402
535
|
if (this.guid == null) {
|
|
403
536
|
return false;
|
|
404
537
|
}
|
|
@@ -461,18 +594,21 @@ class User extends AbleObject_1.default {
|
|
|
461
594
|
}
|
|
462
595
|
return success;
|
|
463
596
|
}
|
|
464
|
-
$addGroup(group) {
|
|
465
|
-
|
|
466
|
-
|
|
597
|
+
async $addGroup(group) {
|
|
598
|
+
await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
|
|
599
|
+
let groups = this.$data.groups;
|
|
600
|
+
if (groups == null) {
|
|
601
|
+
groups = [];
|
|
467
602
|
}
|
|
468
|
-
if (!group.$inArray(
|
|
469
|
-
|
|
470
|
-
|
|
603
|
+
if (!group.$inArray(groups)) {
|
|
604
|
+
groups.push(group);
|
|
605
|
+
this.$data.groups = groups;
|
|
606
|
+
return groups;
|
|
471
607
|
}
|
|
472
608
|
return true;
|
|
473
609
|
}
|
|
474
610
|
$checkPassword(password) {
|
|
475
|
-
const tilmeld = this
|
|
611
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
476
612
|
switch (tilmeld.config.pwMethod) {
|
|
477
613
|
case 'plain':
|
|
478
614
|
return this.$data.password === password;
|
|
@@ -484,10 +620,12 @@ class User extends AbleObject_1.default {
|
|
|
484
620
|
(0, sha256_1.default)(password + this.$data.salt).toString(enc_base64_1.default));
|
|
485
621
|
}
|
|
486
622
|
}
|
|
487
|
-
$delGroup(group) {
|
|
488
|
-
|
|
623
|
+
async $delGroup(group) {
|
|
624
|
+
await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
|
|
625
|
+
let groups = this.$data.groups || [];
|
|
626
|
+
if (this.$data.groups != null && group.$inArray(groups)) {
|
|
489
627
|
const newGroups = [];
|
|
490
|
-
for (let curGroup of
|
|
628
|
+
for (let curGroup of groups) {
|
|
491
629
|
if (!group.$is(curGroup)) {
|
|
492
630
|
newGroups.push(curGroup);
|
|
493
631
|
}
|
|
@@ -497,7 +635,7 @@ class User extends AbleObject_1.default {
|
|
|
497
635
|
}
|
|
498
636
|
return true;
|
|
499
637
|
}
|
|
500
|
-
$inGroup(group) {
|
|
638
|
+
async $inGroup(group) {
|
|
501
639
|
if (typeof group === 'string') {
|
|
502
640
|
if (this.$data.group?.guid === group) {
|
|
503
641
|
return true;
|
|
@@ -511,13 +649,16 @@ class User extends AbleObject_1.default {
|
|
|
511
649
|
}
|
|
512
650
|
return (group.$is(this.$data.group) || group.$inArray(this.$data.groups ?? []));
|
|
513
651
|
}
|
|
514
|
-
$isDescendant(group) {
|
|
515
|
-
|
|
516
|
-
|
|
652
|
+
async $isDescendant(group) {
|
|
653
|
+
await this.$data.group?.$wake();
|
|
654
|
+
if (this.$data.group != null &&
|
|
655
|
+
this.$data.group?.cdate != null &&
|
|
656
|
+
(await this.$data.group?.$isDescendant(group))) {
|
|
517
657
|
return true;
|
|
518
658
|
}
|
|
659
|
+
await Promise.all(this.$data.groups?.map((e) => e.$wake()) || []);
|
|
519
660
|
for (let curGroup of this.$data.groups ?? []) {
|
|
520
|
-
if (curGroup.$isDescendant(group)) {
|
|
661
|
+
if (await curGroup.$isDescendant(group)) {
|
|
521
662
|
return true;
|
|
522
663
|
}
|
|
523
664
|
}
|
|
@@ -531,7 +672,14 @@ class User extends AbleObject_1.default {
|
|
|
531
672
|
return { result: false, message: 'Incorrect password.' };
|
|
532
673
|
}
|
|
533
674
|
this.$data.passwordTemp = data.newPassword;
|
|
675
|
+
if (data.revokeCurrentTokens) {
|
|
676
|
+
this.$data.revokeTokenDate = Date.now();
|
|
677
|
+
}
|
|
534
678
|
if (await this.$save()) {
|
|
679
|
+
if (data.revokeCurrentTokens) {
|
|
680
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
681
|
+
tilmeld.login(this, true);
|
|
682
|
+
}
|
|
535
683
|
return { result: true, message: 'Your password has been changed.' };
|
|
536
684
|
}
|
|
537
685
|
else {
|
|
@@ -539,7 +687,7 @@ class User extends AbleObject_1.default {
|
|
|
539
687
|
}
|
|
540
688
|
}
|
|
541
689
|
$password(password) {
|
|
542
|
-
const tilmeld = this
|
|
690
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
543
691
|
switch (tilmeld.config.pwMethod) {
|
|
544
692
|
case 'plain':
|
|
545
693
|
delete this.$data.salt;
|
|
@@ -557,8 +705,137 @@ class User extends AbleObject_1.default {
|
|
|
557
705
|
}
|
|
558
706
|
return this.$data.password;
|
|
559
707
|
}
|
|
708
|
+
async $revokeCurrentTokens(data) {
|
|
709
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
710
|
+
return { result: false, message: 'Incorrect password.' };
|
|
711
|
+
}
|
|
712
|
+
this.$data.revokeTokenDate = Date.now();
|
|
713
|
+
if (await this.$save()) {
|
|
714
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
715
|
+
tilmeld.login(this, true);
|
|
716
|
+
return {
|
|
717
|
+
result: true,
|
|
718
|
+
message: 'You have logged out of all other sessions.',
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
return { result: false, message: "Couldn't save revocation date." };
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
async $hasTOTPSecret() {
|
|
726
|
+
return this.$data.totpSecret != null;
|
|
727
|
+
}
|
|
728
|
+
$checkTOTPCode(code) {
|
|
729
|
+
if (this.$data.totpSecret == null) {
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
733
|
+
const totp = new otpauth_1.TOTP({
|
|
734
|
+
issuer: tilmeld.config.appName,
|
|
735
|
+
label: this.$data.username,
|
|
736
|
+
algorithm: 'SHA1',
|
|
737
|
+
digits: 6,
|
|
738
|
+
period: 30,
|
|
739
|
+
secret: this.$data.totpSecret,
|
|
740
|
+
});
|
|
741
|
+
return totp.validate({ token: code, window: 2 }) != null;
|
|
742
|
+
}
|
|
743
|
+
async $getNewTOTPSecret() {
|
|
744
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
745
|
+
if (this.$data.totpSecret != null) {
|
|
746
|
+
throw new errors_1.BadDataError('You already have a 2FA secret.');
|
|
747
|
+
}
|
|
748
|
+
const secret = new otpauth_1.Secret();
|
|
749
|
+
const totp = new otpauth_1.TOTP({
|
|
750
|
+
issuer: tilmeld.config.appName,
|
|
751
|
+
label: this.$data.username,
|
|
752
|
+
algorithm: 'SHA1',
|
|
753
|
+
digits: 6,
|
|
754
|
+
period: 30,
|
|
755
|
+
secret,
|
|
756
|
+
});
|
|
757
|
+
const uri = totp.toString();
|
|
758
|
+
const qrcode = await (0, qrcode_1.toDataURL)(uri);
|
|
759
|
+
return {
|
|
760
|
+
uri,
|
|
761
|
+
qrcode,
|
|
762
|
+
secret: secret.base32,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
async $saveTOTPSecret(data) {
|
|
766
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
767
|
+
return { result: false, message: 'Incorrect password.' };
|
|
768
|
+
}
|
|
769
|
+
if (this.$data.totpSecret != null) {
|
|
770
|
+
return { result: false, message: 'You already have a 2FA secret.' };
|
|
771
|
+
}
|
|
772
|
+
if (data.secret == null ||
|
|
773
|
+
typeof data.secret !== 'string' ||
|
|
774
|
+
data.secret === '') {
|
|
775
|
+
return { result: false, message: '2FA secret is invalid.' };
|
|
776
|
+
}
|
|
777
|
+
if (data.code == null ||
|
|
778
|
+
typeof data.code !== 'string' ||
|
|
779
|
+
data.code.length !== 6) {
|
|
780
|
+
return { result: false, message: '2FA code is invalid.' };
|
|
781
|
+
}
|
|
782
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
783
|
+
const totp = new otpauth_1.TOTP({
|
|
784
|
+
issuer: tilmeld.config.appName,
|
|
785
|
+
label: this.$data.username,
|
|
786
|
+
algorithm: 'SHA1',
|
|
787
|
+
digits: 6,
|
|
788
|
+
period: 30,
|
|
789
|
+
secret: data.secret,
|
|
790
|
+
});
|
|
791
|
+
if (totp.validate({ token: data.code, window: 2 }) == null) {
|
|
792
|
+
return { result: false, message: '2FA code is incorrect.' };
|
|
793
|
+
}
|
|
794
|
+
this.$data.totpSecret = data.secret;
|
|
795
|
+
if (await this.$save()) {
|
|
796
|
+
return { result: true, message: 'Your two factor secret is now set.' };
|
|
797
|
+
}
|
|
798
|
+
else {
|
|
799
|
+
return { result: false, message: "Couldn't save two factor secret." };
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async $removeTOTPSecret(data) {
|
|
803
|
+
if (!this.$checkPassword(data.password ?? '')) {
|
|
804
|
+
return { result: false, message: 'Incorrect password.' };
|
|
805
|
+
}
|
|
806
|
+
if (this.$data.totpSecret == null) {
|
|
807
|
+
return { result: false, message: "You don't have a 2FA secret." };
|
|
808
|
+
}
|
|
809
|
+
if (data.code == null ||
|
|
810
|
+
typeof data.code !== 'string' ||
|
|
811
|
+
data.code.length !== 6) {
|
|
812
|
+
return { result: false, message: '2FA code is invalid.' };
|
|
813
|
+
}
|
|
814
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
815
|
+
const totp = new otpauth_1.TOTP({
|
|
816
|
+
issuer: tilmeld.config.appName,
|
|
817
|
+
label: this.$data.username,
|
|
818
|
+
algorithm: 'SHA1',
|
|
819
|
+
digits: 6,
|
|
820
|
+
period: 30,
|
|
821
|
+
secret: this.$data.totpSecret,
|
|
822
|
+
});
|
|
823
|
+
if (totp.validate({ token: data.code, window: 2 }) == null) {
|
|
824
|
+
return { result: false, message: '2FA code is incorrect.' };
|
|
825
|
+
}
|
|
826
|
+
delete this.$data.totpSecret;
|
|
827
|
+
if (await this.$save()) {
|
|
828
|
+
return {
|
|
829
|
+
result: true,
|
|
830
|
+
message: 'Your two factor secret has been removed.',
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
return { result: false, message: "Couldn't remove two factor secret." };
|
|
835
|
+
}
|
|
836
|
+
}
|
|
560
837
|
async $checkUsername() {
|
|
561
|
-
const tilmeld = this
|
|
838
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
562
839
|
if (!tilmeld.config.emailUsernames) {
|
|
563
840
|
if (this.$data.username == null || !this.$data.username.length) {
|
|
564
841
|
return { result: false, message: 'Please specify a username.' };
|
|
@@ -598,6 +875,17 @@ class User extends AbleObject_1.default {
|
|
|
598
875
|
if (test != null) {
|
|
599
876
|
return { result: false, message: 'That username is taken.' };
|
|
600
877
|
}
|
|
878
|
+
for (let callback of this.constructor
|
|
879
|
+
.checkUsernameCallbacks) {
|
|
880
|
+
if (callback) {
|
|
881
|
+
const result = await callback(this, {
|
|
882
|
+
username: this.$data.username,
|
|
883
|
+
});
|
|
884
|
+
if (!result.result) {
|
|
885
|
+
return { message: 'Username is not available.', ...result };
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
601
889
|
return {
|
|
602
890
|
result: true,
|
|
603
891
|
message: this.guid != null ? 'Username is valid.' : 'Username is available!',
|
|
@@ -621,7 +909,7 @@ class User extends AbleObject_1.default {
|
|
|
621
909
|
}
|
|
622
910
|
}
|
|
623
911
|
async $checkEmail() {
|
|
624
|
-
const tilmeld = this
|
|
912
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
625
913
|
if (this.$data.email == null || !this.$data.email.length) {
|
|
626
914
|
if (tilmeld.config.verifyEmail) {
|
|
627
915
|
return { result: false, message: 'Please specify an email.' };
|
|
@@ -656,7 +944,7 @@ class User extends AbleObject_1.default {
|
|
|
656
944
|
};
|
|
657
945
|
}
|
|
658
946
|
async $checkPhone() {
|
|
659
|
-
const tilmeld = this
|
|
947
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
660
948
|
if (this.$data.phone == null || !this.$data.phone.length) {
|
|
661
949
|
return { result: false, message: 'Please specify a phone number.' };
|
|
662
950
|
}
|
|
@@ -684,7 +972,7 @@ class User extends AbleObject_1.default {
|
|
|
684
972
|
};
|
|
685
973
|
}
|
|
686
974
|
async $register(data) {
|
|
687
|
-
let tilmeld = this
|
|
975
|
+
let tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
688
976
|
if (!tilmeld.config.allowRegistration) {
|
|
689
977
|
return {
|
|
690
978
|
result: false,
|
|
@@ -742,7 +1030,7 @@ class User extends AbleObject_1.default {
|
|
|
742
1030
|
const nymph = this.$nymph;
|
|
743
1031
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
744
1032
|
this.$nymph = tnymph;
|
|
745
|
-
tilmeld = this
|
|
1033
|
+
tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
746
1034
|
try {
|
|
747
1035
|
let generatedPrimaryGroup = null;
|
|
748
1036
|
if (tilmeld.config.generatePrimary) {
|
|
@@ -909,13 +1197,13 @@ class User extends AbleObject_1.default {
|
|
|
909
1197
|
}
|
|
910
1198
|
}
|
|
911
1199
|
async $save() {
|
|
912
|
-
let tilmeld = this
|
|
1200
|
+
let tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
913
1201
|
if (this.$data.username == null || !this.$data.username.trim().length) {
|
|
914
1202
|
return false;
|
|
915
1203
|
}
|
|
916
|
-
if (tilmeld.gatekeeper('tilmeld/admin') &&
|
|
917
|
-
!tilmeld.gatekeeper('system/admin') &&
|
|
918
|
-
this.$
|
|
1204
|
+
if ((await tilmeld.gatekeeper('tilmeld/admin')) &&
|
|
1205
|
+
!(await tilmeld.gatekeeper('system/admin')) &&
|
|
1206
|
+
this.$data.abilities?.includes('system/admin')) {
|
|
919
1207
|
throw new errors_1.BadDataError("You don't have the authority to modify system admins.");
|
|
920
1208
|
}
|
|
921
1209
|
let sendVerification = false;
|
|
@@ -996,7 +1284,7 @@ class User extends AbleObject_1.default {
|
|
|
996
1284
|
throw new errors_1.BadEmailError(emCheck.message);
|
|
997
1285
|
}
|
|
998
1286
|
}
|
|
999
|
-
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1287
|
+
if (!(await tilmeld.gatekeeper('tilmeld/admin'))) {
|
|
1000
1288
|
if (tilmeld.config.verifyEmail) {
|
|
1001
1289
|
if (this.guid == null) {
|
|
1002
1290
|
if ((this.$data.abilities?.indexOf('system/admin') ?? -1) === -1) {
|
|
@@ -1062,17 +1350,18 @@ class User extends AbleObject_1.default {
|
|
|
1062
1350
|
const nymph = this.$nymph;
|
|
1063
1351
|
const tnymph = await this.$nymph.startTransaction(transaction);
|
|
1064
1352
|
this.$nymph = tnymph;
|
|
1065
|
-
tilmeld = this
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1353
|
+
tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
1354
|
+
const group = this.$data.group;
|
|
1355
|
+
await group?.$wake();
|
|
1356
|
+
if (group != null && group.user != null && this.$is(group.user)) {
|
|
1069
1357
|
try {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
await
|
|
1358
|
+
group.groupname = this.$data.username;
|
|
1359
|
+
group.avatar = this.$data.avatar;
|
|
1360
|
+
group.email = this.$data.email;
|
|
1361
|
+
group.name = this.$data.name;
|
|
1362
|
+
group.phone = this.$data.phone;
|
|
1363
|
+
await group.$saveSkipAC();
|
|
1364
|
+
this.$data.group = group;
|
|
1076
1365
|
}
|
|
1077
1366
|
catch (e) {
|
|
1078
1367
|
await tnymph.rollback(transaction);
|
|
@@ -1106,8 +1395,8 @@ class User extends AbleObject_1.default {
|
|
|
1106
1395
|
this.$descendantGroups = undefined;
|
|
1107
1396
|
this.$gatekeeperCache = undefined;
|
|
1108
1397
|
await tnymph.commit(transaction);
|
|
1109
|
-
if (nymph.
|
|
1110
|
-
nymph.
|
|
1398
|
+
if ((0, enforceTilmeld_1.enforceTilmeld)(nymph).User.current(true).$is(this)) {
|
|
1399
|
+
(0, enforceTilmeld_1.enforceTilmeld)(nymph).fillSession(this);
|
|
1111
1400
|
}
|
|
1112
1401
|
}
|
|
1113
1402
|
else {
|
|
@@ -1128,12 +1417,12 @@ class User extends AbleObject_1.default {
|
|
|
1128
1417
|
return false;
|
|
1129
1418
|
}
|
|
1130
1419
|
async $delete() {
|
|
1131
|
-
const tilmeld = this
|
|
1132
|
-
if (!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
1420
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(this);
|
|
1421
|
+
if (!(await tilmeld.gatekeeper('tilmeld/admin'))) {
|
|
1133
1422
|
throw new errors_1.BadDataError("You don't have the authority to delete users.");
|
|
1134
1423
|
}
|
|
1135
|
-
if (!tilmeld.gatekeeper('system/admin') &&
|
|
1136
|
-
this.$
|
|
1424
|
+
if (!(await tilmeld.gatekeeper('system/admin')) &&
|
|
1425
|
+
this.$data.abilities?.includes('system/admin')) {
|
|
1137
1426
|
throw new errors_1.BadDataError("You don't have the authority to delete system admins.");
|
|
1138
1427
|
}
|
|
1139
1428
|
if (tilmeld.User.current(true).$is(this)) {
|
|
@@ -1161,9 +1450,9 @@ class User extends AbleObject_1.default {
|
|
|
1161
1450
|
return true;
|
|
1162
1451
|
}
|
|
1163
1452
|
}
|
|
1164
|
-
exports.default = User;
|
|
1165
1453
|
User.ETYPE = 'tilmeld_user';
|
|
1166
1454
|
User.class = 'User';
|
|
1455
|
+
User.checkUsernameCallbacks = [];
|
|
1167
1456
|
User.beforeRegisterCallbacks = [];
|
|
1168
1457
|
User.afterRegisterCallbacks = [];
|
|
1169
1458
|
User.beforeLoginCallbacks = [];
|
|
@@ -1178,23 +1467,26 @@ User.DEFAULT_CLIENT_ENABLED_METHODS = [
|
|
|
1178
1467
|
'$register',
|
|
1179
1468
|
];
|
|
1180
1469
|
User.DEFAULT_PRIVATE_DATA = [
|
|
1470
|
+
'abilities',
|
|
1181
1471
|
'email',
|
|
1182
|
-
'originalEmail',
|
|
1183
1472
|
'phone',
|
|
1184
1473
|
'group',
|
|
1185
1474
|
'groups',
|
|
1186
|
-
'abilities',
|
|
1187
1475
|
'inheritAbilities',
|
|
1188
|
-
'
|
|
1189
|
-
'recoverSecretDate',
|
|
1190
|
-
'password',
|
|
1191
|
-
'salt',
|
|
1476
|
+
'enabled',
|
|
1192
1477
|
'secret',
|
|
1193
|
-
'
|
|
1478
|
+
'emailChangeDate',
|
|
1194
1479
|
'newEmailSecret',
|
|
1195
|
-
'
|
|
1480
|
+
'newEmailAddress',
|
|
1196
1481
|
'cancelEmailSecret',
|
|
1197
|
-
'
|
|
1482
|
+
'cancelEmailAddress',
|
|
1483
|
+
'recoverSecret',
|
|
1484
|
+
'recoverSecretDate',
|
|
1485
|
+
'salt',
|
|
1486
|
+
'password',
|
|
1487
|
+
'passwordTemp',
|
|
1488
|
+
'revokeTokenDate',
|
|
1489
|
+
'totpSecret',
|
|
1198
1490
|
];
|
|
1199
1491
|
User.DEFAULT_ALLOWLIST_DATA = [];
|
|
1200
1492
|
User.clientEnabledStaticMethods = [
|
|
@@ -1205,4 +1497,5 @@ User.clientEnabledStaticMethods = [
|
|
|
1205
1497
|
'getClientConfig',
|
|
1206
1498
|
];
|
|
1207
1499
|
User.searchRestrictedData = [...User.DEFAULT_PRIVATE_DATA];
|
|
1500
|
+
exports.default = User;
|
|
1208
1501
|
//# sourceMappingURL=User.js.map
|