@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/Tilmeld.js
CHANGED
|
@@ -10,6 +10,7 @@ const conf_1 = require("./conf");
|
|
|
10
10
|
const errors_1 = require("./errors");
|
|
11
11
|
const Group_1 = __importDefault(require("./Group"));
|
|
12
12
|
const User_1 = __importDefault(require("./User"));
|
|
13
|
+
const enforceTilmeld_1 = require("./enforceTilmeld");
|
|
13
14
|
class Tilmeld {
|
|
14
15
|
constructor(config) {
|
|
15
16
|
this.nymph = {};
|
|
@@ -18,7 +19,7 @@ class Tilmeld {
|
|
|
18
19
|
this.Group = Group_1.default;
|
|
19
20
|
this.request = null;
|
|
20
21
|
this.response = null;
|
|
21
|
-
this.
|
|
22
|
+
this.alreadyLoggedOutSwitch = false;
|
|
22
23
|
this.config = { ...conf_1.ConfigDefaults, ...config };
|
|
23
24
|
}
|
|
24
25
|
clone() {
|
|
@@ -26,7 +27,6 @@ class Tilmeld {
|
|
|
26
27
|
tilmeld.request = this.request;
|
|
27
28
|
tilmeld.response = this.response;
|
|
28
29
|
tilmeld.currentUser = this.currentUser;
|
|
29
|
-
tilmeld.skipAuthenticate = true;
|
|
30
30
|
return tilmeld;
|
|
31
31
|
}
|
|
32
32
|
init(nymph) {
|
|
@@ -34,41 +34,48 @@ class Tilmeld {
|
|
|
34
34
|
if (this.nymph.driver == null) {
|
|
35
35
|
throw new Error("Tilmeld can't be configured before Nymph.");
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
if (nymph.parent) {
|
|
38
|
+
this.User = this.nymph.getEntityClass(User_1.default);
|
|
39
|
+
this.Group = this.nymph.getEntityClass(Group_1.default);
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.
|
|
44
|
-
|
|
41
|
+
else {
|
|
42
|
+
this.User = this.nymph.addEntityClass(User_1.default);
|
|
43
|
+
this.Group = this.nymph.addEntityClass(Group_1.default);
|
|
44
|
+
}
|
|
45
|
+
if (this.currentUser) {
|
|
46
|
+
const currentUserGUID = this.currentUser.guid;
|
|
47
|
+
const currentUserCDate = this.currentUser.cdate;
|
|
48
|
+
const currentUserMDate = this.currentUser.mdate;
|
|
49
|
+
const currentUserTags = this.currentUser.tags;
|
|
50
|
+
const currentUserData = this.currentUser.$getData();
|
|
51
|
+
const currentUserSData = this.currentUser.$getSData();
|
|
52
|
+
const user = this.User.factorySync();
|
|
53
|
+
user.guid = currentUserGUID;
|
|
54
|
+
user.cdate = currentUserCDate;
|
|
55
|
+
user.mdate = currentUserMDate;
|
|
56
|
+
user.tags = currentUserTags;
|
|
57
|
+
user.$putData(currentUserData, currentUserSData);
|
|
58
|
+
this.fillSession(user);
|
|
45
59
|
}
|
|
46
|
-
NymphGroup.nymph = this.nymph;
|
|
47
|
-
NymphGroup.tilmeld = this;
|
|
48
|
-
NymphUser.skipOnClone = true;
|
|
49
|
-
this.Group = NymphGroup;
|
|
50
|
-
this.nymph.addEntityClass(NymphGroup);
|
|
51
60
|
this.initAccessControl();
|
|
52
|
-
if (this.request != null && !this.skipAuthenticate) {
|
|
53
|
-
this.authenticate();
|
|
54
|
-
}
|
|
55
|
-
this.skipAuthenticate = false;
|
|
56
61
|
}
|
|
57
|
-
gatekeeper(ability) {
|
|
62
|
+
async gatekeeper(ability) {
|
|
58
63
|
if (this.currentUser == null) {
|
|
59
64
|
return false;
|
|
60
65
|
}
|
|
61
|
-
return this.currentUser.$gatekeeper(ability);
|
|
66
|
+
return await this.currentUser.$gatekeeper(ability);
|
|
62
67
|
}
|
|
63
68
|
initAccessControl() {
|
|
64
69
|
const handleQuery = function (nymph, options, selectors) {
|
|
65
|
-
const tilmeld = nymph
|
|
70
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(nymph);
|
|
66
71
|
if (!options ||
|
|
67
72
|
!('skipAc' in options) ||
|
|
68
73
|
!options.skipAc ||
|
|
69
74
|
options.source === 'client') {
|
|
70
75
|
if (options?.source === 'client') {
|
|
71
|
-
if (!tilmeld.
|
|
76
|
+
if ((!tilmeld.currentUser ||
|
|
77
|
+
(!tilmeld.currentUser.abilities?.includes('tilmeld/admin') &&
|
|
78
|
+
!tilmeld.currentUser.abilities?.includes('system/admin'))) &&
|
|
72
79
|
((!tilmeld.config.enableUserSearch &&
|
|
73
80
|
options.class?.factorySync() instanceof User_1.default) ||
|
|
74
81
|
(!tilmeld.config.enableGroupSearch &&
|
|
@@ -90,7 +97,7 @@ class Tilmeld {
|
|
|
90
97
|
};
|
|
91
98
|
handleQuery.skipOnClone = true;
|
|
92
99
|
const checkPermissionsDelete = async function (nymph, entity) {
|
|
93
|
-
const tilmeld = nymph
|
|
100
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(nymph);
|
|
94
101
|
if (typeof entity.$tilmeldDeleteSkipAC === 'function' &&
|
|
95
102
|
entity.$tilmeldDeleteSkipAC()) {
|
|
96
103
|
return;
|
|
@@ -101,14 +108,14 @@ class Tilmeld {
|
|
|
101
108
|
};
|
|
102
109
|
checkPermissionsDelete.skipOnClone = true;
|
|
103
110
|
const checkPermissionsDeleteByID = async function (nymph, guid, className) {
|
|
104
|
-
const entity = nymph.
|
|
111
|
+
const entity = await nymph.getEntity({ class: nymph.getEntityClass(className ?? 'Entity') }, { type: '&', guid: guid });
|
|
105
112
|
if (entity != null) {
|
|
106
113
|
checkPermissionsDelete(nymph, entity);
|
|
107
114
|
}
|
|
108
115
|
};
|
|
109
116
|
checkPermissionsDeleteByID.skipOnClone = true;
|
|
110
117
|
const checkPermissionsSaveAndFilterAcChanges = async function (nymph, entity) {
|
|
111
|
-
const tilmeld = nymph
|
|
118
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(nymph);
|
|
112
119
|
if (!entity) {
|
|
113
120
|
return;
|
|
114
121
|
}
|
|
@@ -118,28 +125,7 @@ class Tilmeld {
|
|
|
118
125
|
}
|
|
119
126
|
if (entity.guid != null) {
|
|
120
127
|
const originalAc = entity.$getOriginalAcValues();
|
|
121
|
-
const newAc =
|
|
122
|
-
user: entity.user ?? undefined,
|
|
123
|
-
group: entity.group ?? undefined,
|
|
124
|
-
acUser: entity.acUser ?? undefined,
|
|
125
|
-
acGroup: entity.acGroup ?? undefined,
|
|
126
|
-
acOther: entity.acOther ?? undefined,
|
|
127
|
-
acRead: entity.acRead ?? undefined,
|
|
128
|
-
acWrite: entity.acWrite ?? undefined,
|
|
129
|
-
acFull: entity.acFull ?? undefined,
|
|
130
|
-
};
|
|
131
|
-
const setAcProperties = (acValues) => {
|
|
132
|
-
for (let name in acValues) {
|
|
133
|
-
const value = acValues[name];
|
|
134
|
-
if (value == null) {
|
|
135
|
-
delete entity[name];
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
entity[name] = value;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
setAcProperties(originalAc);
|
|
128
|
+
const newAc = entity.$getCurrentAcValues();
|
|
143
129
|
function areAcPropertiesChanged(a, b) {
|
|
144
130
|
for (const name of ['user', 'group']) {
|
|
145
131
|
const aVal = a[name];
|
|
@@ -150,7 +136,7 @@ class Tilmeld {
|
|
|
150
136
|
else if (aVal == null || bVal == null) {
|
|
151
137
|
return true;
|
|
152
138
|
}
|
|
153
|
-
if (
|
|
139
|
+
if (aVal !== bVal) {
|
|
154
140
|
return true;
|
|
155
141
|
}
|
|
156
142
|
}
|
|
@@ -179,31 +165,29 @@ class Tilmeld {
|
|
|
179
165
|
if (aVal.length !== bVal.length) {
|
|
180
166
|
return true;
|
|
181
167
|
}
|
|
182
|
-
if ((0, lodash_1.xor)(aVal
|
|
168
|
+
if ((0, lodash_1.xor)(aVal, bVal).length) {
|
|
183
169
|
return true;
|
|
184
170
|
}
|
|
185
171
|
}
|
|
186
172
|
return false;
|
|
187
173
|
}
|
|
188
174
|
if (areAcPropertiesChanged(originalAc, newAc)) {
|
|
189
|
-
if (!tilmeld.checkPermissions(entity, nymph_1.TilmeldAccessLevels.FULL_ACCESS)) {
|
|
175
|
+
if (!tilmeld.checkPermissions(entity, nymph_1.TilmeldAccessLevels.FULL_ACCESS, undefined, originalAc)) {
|
|
190
176
|
throw new errors_1.AccessControlError('No permission to change access control properties.');
|
|
191
177
|
}
|
|
192
|
-
if ((
|
|
178
|
+
if ((originalAc.user && originalAc.user !== newAc.user) ||
|
|
193
179
|
(!originalAc.user &&
|
|
194
180
|
newAc.user &&
|
|
195
|
-
|
|
196
|
-
!tilmeld.gatekeeper('tilmeld/admin')) {
|
|
181
|
+
newAc.user !== tilmeld.currentUser)) {
|
|
197
182
|
throw new errors_1.AccessControlError('No permission to assign to another user.');
|
|
198
183
|
}
|
|
199
184
|
if (newAc.group &&
|
|
200
|
-
|
|
201
|
-
!(newAc.group
|
|
202
|
-
|
|
203
|
-
|
|
185
|
+
newAc.group !== originalAc.group &&
|
|
186
|
+
!(newAc.group =
|
|
187
|
+
tilmeld.currentUser?.$getGid() ||
|
|
188
|
+
(tilmeld.currentUser?.$getGids() ?? []).includes(newAc.group))) {
|
|
204
189
|
throw new errors_1.AccessControlError('No permission to assign to another group.');
|
|
205
190
|
}
|
|
206
|
-
setAcProperties(newAc);
|
|
207
191
|
}
|
|
208
192
|
}
|
|
209
193
|
if (!tilmeld.checkPermissions(entity, nymph_1.TilmeldAccessLevels.WRITE_ACCESS)) {
|
|
@@ -212,7 +196,7 @@ class Tilmeld {
|
|
|
212
196
|
};
|
|
213
197
|
checkPermissionsSaveAndFilterAcChanges.skipOnClone = true;
|
|
214
198
|
const addAccess = async function (nymph, entity) {
|
|
215
|
-
const tilmeld = nymph
|
|
199
|
+
const tilmeld = (0, enforceTilmeld_1.enforceTilmeld)(nymph);
|
|
216
200
|
const user = tilmeld.currentUser;
|
|
217
201
|
if (user != null &&
|
|
218
202
|
entity.guid == null &&
|
|
@@ -221,10 +205,11 @@ class Tilmeld {
|
|
|
221
205
|
if (entity.user == null) {
|
|
222
206
|
entity.user = user;
|
|
223
207
|
}
|
|
224
|
-
if (entity.group == null
|
|
225
|
-
user.group
|
|
226
|
-
|
|
227
|
-
|
|
208
|
+
if (entity.group == null) {
|
|
209
|
+
const group = user.group;
|
|
210
|
+
if (group != null && group.guid != null) {
|
|
211
|
+
entity.group = group;
|
|
212
|
+
}
|
|
228
213
|
}
|
|
229
214
|
if (entity.acUser == null) {
|
|
230
215
|
entity.acUser = nymph_1.TilmeldAccessLevels.FULL_ACCESS;
|
|
@@ -306,10 +291,6 @@ class Tilmeld {
|
|
|
306
291
|
}
|
|
307
292
|
addAccessControlSelectors(options, selectors) {
|
|
308
293
|
const user = this.currentUser;
|
|
309
|
-
if (user != null &&
|
|
310
|
-
(user.abilities?.indexOf('system/admin') ?? -1) !== -1) {
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
294
|
if (options == null) {
|
|
314
295
|
throw new Error('No options in argument.');
|
|
315
296
|
}
|
|
@@ -344,27 +325,19 @@ class Tilmeld {
|
|
|
344
325
|
];
|
|
345
326
|
const groupRefs = [];
|
|
346
327
|
const acRefs = [];
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
acRefs.push(['
|
|
351
|
-
acRefs.push(['
|
|
328
|
+
const gid = user.$getGid();
|
|
329
|
+
if (gid != null) {
|
|
330
|
+
groupRefs.push(['group', gid]);
|
|
331
|
+
acRefs.push(['acRead', gid]);
|
|
332
|
+
acRefs.push(['acWrite', gid]);
|
|
333
|
+
acRefs.push(['acFull', gid]);
|
|
352
334
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
for (let curDescendantGroup of user.$getDescendantGroupsSync()) {
|
|
362
|
-
if (curDescendantGroup != null && curDescendantGroup.guid != null) {
|
|
363
|
-
groupRefs.push(['group', curDescendantGroup.guid]);
|
|
364
|
-
acRefs.push(['acRead', curDescendantGroup.guid]);
|
|
365
|
-
acRefs.push(['acWrite', curDescendantGroup.guid]);
|
|
366
|
-
acRefs.push(['acFull', curDescendantGroup.guid]);
|
|
367
|
-
}
|
|
335
|
+
const gids = user.$getGids();
|
|
336
|
+
for (let curGid of gids ?? []) {
|
|
337
|
+
groupRefs.push(['group', curGid]);
|
|
338
|
+
acRefs.push(['acRead', curGid]);
|
|
339
|
+
acRefs.push(['acWrite', curGid]);
|
|
340
|
+
acRefs.push(['acFull', curGid]);
|
|
368
341
|
}
|
|
369
342
|
if (groupRefs.length) {
|
|
370
343
|
subSelectors.push({
|
|
@@ -397,9 +370,9 @@ class Tilmeld {
|
|
|
397
370
|
selectors.push(selector);
|
|
398
371
|
}
|
|
399
372
|
}
|
|
400
|
-
checkPermissions(entity, type = nymph_1.TilmeldAccessLevels.READ_ACCESS, user) {
|
|
401
|
-
if (
|
|
402
|
-
|
|
373
|
+
checkPermissions(entity, type = nymph_1.TilmeldAccessLevels.READ_ACCESS, user, acProperties) {
|
|
374
|
+
if (!acProperties) {
|
|
375
|
+
acProperties = entity.$getCurrentAcValues();
|
|
403
376
|
}
|
|
404
377
|
let userOrNull = null;
|
|
405
378
|
let userOrEmpty = this.User.factorySync();
|
|
@@ -411,75 +384,64 @@ class Tilmeld {
|
|
|
411
384
|
userOrNull = user;
|
|
412
385
|
userOrEmpty = user;
|
|
413
386
|
}
|
|
414
|
-
if (userOrEmpty.$gatekeeper('system/admin')) {
|
|
415
|
-
return true;
|
|
416
|
-
}
|
|
417
387
|
if ((entity instanceof User_1.default || entity instanceof Group_1.default) &&
|
|
418
388
|
(type === nymph_1.TilmeldAccessLevels.READ_ACCESS ||
|
|
419
|
-
userOrEmpty
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
if (entity.user == null && entity.group == null) {
|
|
389
|
+
userOrEmpty.abilities?.includes('tilmeld/admin') ||
|
|
390
|
+
userOrEmpty.abilities?.includes('system/admin'))) {
|
|
423
391
|
return true;
|
|
424
392
|
}
|
|
425
|
-
const acUser =
|
|
426
|
-
const acGroup =
|
|
427
|
-
const acOther =
|
|
428
|
-
if (userOrNull
|
|
393
|
+
const acUser = acProperties.acUser ?? nymph_1.TilmeldAccessLevels.FULL_ACCESS;
|
|
394
|
+
const acGroup = acProperties.acGroup ?? nymph_1.TilmeldAccessLevels.READ_ACCESS;
|
|
395
|
+
const acOther = acProperties.acOther ?? nymph_1.TilmeldAccessLevels.NO_ACCESS;
|
|
396
|
+
if (userOrNull == null) {
|
|
429
397
|
return acOther >= type;
|
|
430
398
|
}
|
|
431
399
|
if (userOrEmpty.$is(entity)) {
|
|
432
400
|
return true;
|
|
433
401
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
402
|
+
const gid = userOrEmpty.$getGid();
|
|
403
|
+
if (gid != null &&
|
|
404
|
+
entity.guid === gid &&
|
|
437
405
|
type === nymph_1.TilmeldAccessLevels.READ_ACCESS) {
|
|
438
406
|
return true;
|
|
439
407
|
}
|
|
440
|
-
let
|
|
441
|
-
|
|
442
|
-
allGroups = allGroups.concat(userOrEmpty.$getDescendantGroupsSync());
|
|
408
|
+
let allGids = gid == null ? [] : [gid];
|
|
409
|
+
allGids = allGids.concat(userOrEmpty.$getGids() ?? []);
|
|
443
410
|
const checks = [
|
|
444
411
|
{
|
|
445
412
|
type: nymph_1.TilmeldAccessLevels.FULL_ACCESS,
|
|
446
|
-
array: [...(
|
|
413
|
+
array: [...(acProperties.acFull ?? [])],
|
|
447
414
|
},
|
|
448
415
|
{
|
|
449
416
|
type: nymph_1.TilmeldAccessLevels.WRITE_ACCESS,
|
|
450
|
-
array: [...(
|
|
417
|
+
array: [...(acProperties.acWrite ?? [])],
|
|
451
418
|
},
|
|
452
419
|
{
|
|
453
420
|
type: nymph_1.TilmeldAccessLevels.READ_ACCESS,
|
|
454
|
-
array: [...(
|
|
421
|
+
array: [...(acProperties.acRead ?? [])],
|
|
455
422
|
},
|
|
456
423
|
];
|
|
457
424
|
for (let curCheck of checks) {
|
|
458
425
|
if (type <= curCheck.type) {
|
|
459
|
-
if (
|
|
426
|
+
if (curCheck.array.includes(userOrEmpty.guid)) {
|
|
460
427
|
return true;
|
|
461
428
|
}
|
|
462
|
-
for (let
|
|
463
|
-
if (
|
|
464
|
-
curGroup.$inArray(curCheck.array)) {
|
|
429
|
+
for (let curGid of allGids) {
|
|
430
|
+
if (curCheck.array.includes(curGid)) {
|
|
465
431
|
return true;
|
|
466
432
|
}
|
|
467
433
|
}
|
|
468
434
|
}
|
|
469
435
|
}
|
|
470
|
-
if (
|
|
471
|
-
typeof entity.user.$is === 'function' &&
|
|
472
|
-
entity.user.$is(userOrNull)) {
|
|
436
|
+
if (acProperties.user != null && acProperties.user === userOrNull.guid) {
|
|
473
437
|
return acUser >= type;
|
|
474
438
|
}
|
|
475
|
-
if (
|
|
476
|
-
typeof entity.group.$inArray === 'function' &&
|
|
477
|
-
entity.group.$inArray(allGroups)) {
|
|
439
|
+
if (acProperties.group != null && allGids.includes(acProperties.group)) {
|
|
478
440
|
return acGroup >= type;
|
|
479
441
|
}
|
|
480
442
|
return acOther >= type;
|
|
481
443
|
}
|
|
482
|
-
checkClientUIDPermissions(name, type = nymph_1.TilmeldAccessLevels.READ_ACCESS, user) {
|
|
444
|
+
async checkClientUIDPermissions(name, type = nymph_1.TilmeldAccessLevels.READ_ACCESS, user) {
|
|
483
445
|
let userOrEmpty = this.User.factorySync();
|
|
484
446
|
if (user == null) {
|
|
485
447
|
userOrEmpty = this.User.current(true);
|
|
@@ -487,52 +449,40 @@ class Tilmeld {
|
|
|
487
449
|
else if (user !== false) {
|
|
488
450
|
userOrEmpty = user;
|
|
489
451
|
}
|
|
490
|
-
if (userOrEmpty
|
|
452
|
+
if (userOrEmpty.abilities?.includes('system/admin')) {
|
|
491
453
|
return true;
|
|
492
454
|
}
|
|
493
455
|
if (type === nymph_1.TilmeldAccessLevels.FULL_ACCESS) {
|
|
494
456
|
return (this.config.clientSetabledUIDs.indexOf(name) !== -1 ||
|
|
495
|
-
userOrEmpty.$gatekeeper(`uid/set/${name}`));
|
|
457
|
+
(await userOrEmpty.$gatekeeper(`uid/set/${name}`)));
|
|
496
458
|
}
|
|
497
459
|
else if (type === nymph_1.TilmeldAccessLevels.WRITE_ACCESS) {
|
|
498
460
|
return (this.config.clientEnabledUIDs.indexOf(name) !== -1 ||
|
|
499
461
|
this.config.clientSetabledUIDs.indexOf(name) !== -1 ||
|
|
500
|
-
userOrEmpty.$gatekeeper(`uid/new/${name}`) ||
|
|
501
|
-
userOrEmpty.$gatekeeper(`uid/set/${name}`));
|
|
462
|
+
(await userOrEmpty.$gatekeeper(`uid/new/${name}`)) ||
|
|
463
|
+
(await userOrEmpty.$gatekeeper(`uid/set/${name}`)));
|
|
502
464
|
}
|
|
503
465
|
else if (type === nymph_1.TilmeldAccessLevels.READ_ACCESS) {
|
|
504
466
|
return (this.config.clientReadableUIDs.indexOf(name) !== -1 ||
|
|
505
467
|
this.config.clientEnabledUIDs.indexOf(name) !== -1 ||
|
|
506
468
|
this.config.clientSetabledUIDs.indexOf(name) !== -1 ||
|
|
507
|
-
userOrEmpty.$gatekeeper(`uid/get/${name}`) ||
|
|
508
|
-
userOrEmpty.$gatekeeper(`uid/new/${name}`) ||
|
|
509
|
-
userOrEmpty.$gatekeeper(`uid/set/${name}`));
|
|
469
|
+
(await userOrEmpty.$gatekeeper(`uid/get/${name}`)) ||
|
|
470
|
+
(await userOrEmpty.$gatekeeper(`uid/new/${name}`)) ||
|
|
471
|
+
(await userOrEmpty.$gatekeeper(`uid/set/${name}`)));
|
|
510
472
|
}
|
|
511
473
|
return false;
|
|
512
474
|
}
|
|
513
475
|
fillSession(user) {
|
|
514
|
-
const _group = user.group;
|
|
515
|
-
const _groups = user.groups;
|
|
516
476
|
this.currentUser = user;
|
|
517
477
|
this.currentUser.$updateDataProtection();
|
|
518
|
-
|
|
519
|
-
this.currentUser.group.$updateDataProtection();
|
|
520
|
-
}
|
|
521
|
-
for (let group of this.currentUser.groups ?? []) {
|
|
522
|
-
group.$updateDataProtection();
|
|
523
|
-
}
|
|
478
|
+
this.currentUser.$updateGroupDataProtection();
|
|
524
479
|
}
|
|
525
480
|
clearSession() {
|
|
526
481
|
const user = this.currentUser;
|
|
527
482
|
this.currentUser = null;
|
|
528
483
|
if (user) {
|
|
529
484
|
user.$updateDataProtection();
|
|
530
|
-
|
|
531
|
-
user.group.$updateDataProtection();
|
|
532
|
-
}
|
|
533
|
-
for (let group of user.groups ?? []) {
|
|
534
|
-
group.$updateDataProtection();
|
|
535
|
-
}
|
|
485
|
+
user.$updateGroupDataProtection();
|
|
536
486
|
}
|
|
537
487
|
}
|
|
538
488
|
async extractToken(token) {
|
|
@@ -545,89 +495,190 @@ class Tilmeld {
|
|
|
545
495
|
type: '&',
|
|
546
496
|
guid: guid,
|
|
547
497
|
});
|
|
548
|
-
if (!user || !user.guid
|
|
498
|
+
if (!user || !user.guid) {
|
|
549
499
|
return null;
|
|
550
500
|
}
|
|
551
501
|
return user;
|
|
552
502
|
}
|
|
553
|
-
authenticate(skipXsrfToken = false) {
|
|
503
|
+
async authenticate(skipXsrfToken = false) {
|
|
554
504
|
if (this.request == null) {
|
|
555
505
|
return false;
|
|
556
506
|
}
|
|
507
|
+
if (this.response &&
|
|
508
|
+
this.response.locals.user &&
|
|
509
|
+
this.response.locals.user instanceof this.User) {
|
|
510
|
+
const user = this.response.locals.user;
|
|
511
|
+
this.fillSession(user);
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
557
514
|
const cookies = this.request.cookies ?? {};
|
|
558
515
|
let fromAuthHeader = false;
|
|
559
516
|
let authToken;
|
|
517
|
+
let switchToken;
|
|
560
518
|
if (this.request.header('x-tilmeldauth') != null) {
|
|
561
519
|
fromAuthHeader = true;
|
|
562
520
|
authToken = this.request.header('x-tilmeldauth');
|
|
521
|
+
switchToken =
|
|
522
|
+
this.request.header('x-tilmeldswitch') ||
|
|
523
|
+
'TILMELDSWITCH' in cookies
|
|
524
|
+
? cookies.TILMELDSWITCH
|
|
525
|
+
: null;
|
|
563
526
|
}
|
|
564
527
|
else if ('TILMELDAUTH' in cookies) {
|
|
565
528
|
fromAuthHeader = false;
|
|
566
529
|
authToken = cookies.TILMELDAUTH;
|
|
530
|
+
switchToken = 'TILMELDSWITCH' in cookies ? cookies.TILMELDSWITCH : null;
|
|
567
531
|
}
|
|
568
532
|
else {
|
|
569
533
|
return false;
|
|
570
534
|
}
|
|
571
|
-
let
|
|
535
|
+
let authExtract;
|
|
536
|
+
let switchExtract;
|
|
572
537
|
if (skipXsrfToken ||
|
|
573
538
|
this.request.originalUrl.startsWith(this.config.setupPath)) {
|
|
574
|
-
|
|
539
|
+
authExtract = this.config.jwtExtract(this.config, authToken);
|
|
540
|
+
switchExtract = switchToken
|
|
541
|
+
? this.config.jwtExtract(this.config, switchToken)
|
|
542
|
+
: null;
|
|
575
543
|
}
|
|
576
544
|
else {
|
|
577
545
|
const xsrfToken = this.request.header('x-xsrf-token');
|
|
578
546
|
if (xsrfToken == null && !fromAuthHeader) {
|
|
579
547
|
return false;
|
|
580
548
|
}
|
|
581
|
-
|
|
549
|
+
authExtract = this.config.jwtExtract(this.config, authToken, xsrfToken);
|
|
550
|
+
switchExtract = switchToken
|
|
551
|
+
? this.config.jwtExtract(this.config, switchToken)
|
|
552
|
+
: null;
|
|
582
553
|
}
|
|
583
|
-
if (
|
|
584
|
-
this.logout();
|
|
554
|
+
if (authExtract == null) {
|
|
555
|
+
await this.logout();
|
|
585
556
|
return false;
|
|
586
557
|
}
|
|
587
|
-
const { guid, expire } =
|
|
588
|
-
const
|
|
589
|
-
|
|
590
|
-
|
|
558
|
+
const { guid, issued, expire } = authExtract;
|
|
559
|
+
const { guid: switchGuid, expire: switchExpire } = switchExtract || {
|
|
560
|
+
guid: null,
|
|
561
|
+
expire: null,
|
|
562
|
+
};
|
|
563
|
+
const user = await this.User.factory(guid);
|
|
564
|
+
if (user.guid == null ||
|
|
565
|
+
!user.enabled ||
|
|
566
|
+
expire.getTime() <= Date.now() ||
|
|
567
|
+
issued.getTime() > Date.now() ||
|
|
568
|
+
(user.revokeTokenDate != null && issued.getTime() <= user.revokeTokenDate)) {
|
|
569
|
+
await this.logout();
|
|
591
570
|
return false;
|
|
592
571
|
}
|
|
593
|
-
if (
|
|
572
|
+
if (switchGuid && switchExpire && switchExpire.getTime() > Date.now()) {
|
|
573
|
+
const switchUser = await this.User.factory(switchGuid);
|
|
574
|
+
if (switchUser.guid == null) {
|
|
575
|
+
await this.logoutSwitch();
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
this.fillSession(switchUser);
|
|
579
|
+
if (this.response) {
|
|
580
|
+
this.response.locals.user = switchUser;
|
|
581
|
+
}
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (expire.getTime() < Date.now() + this.config.jwtRenew * 1000) {
|
|
594
586
|
this.login(user, fromAuthHeader);
|
|
595
587
|
}
|
|
596
588
|
else {
|
|
597
589
|
this.fillSession(user);
|
|
598
590
|
}
|
|
591
|
+
if (this.response) {
|
|
592
|
+
this.response.locals.user = user;
|
|
593
|
+
}
|
|
599
594
|
return true;
|
|
600
595
|
}
|
|
601
|
-
login(user, sendAuthHeader) {
|
|
596
|
+
login(user, sendAuthHeader, sendCookie = true) {
|
|
602
597
|
if (user.guid != null && user.enabled) {
|
|
603
|
-
if (this.response
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
598
|
+
if (this.response) {
|
|
599
|
+
if (!this.response.headersSent) {
|
|
600
|
+
const token = this.config.jwtBuilder(this.config, user);
|
|
601
|
+
if (sendCookie) {
|
|
602
|
+
const appUrl = new url_1.URL(this.config.appUrl);
|
|
603
|
+
this.response.cookie('TILMELDAUTH', token, {
|
|
604
|
+
domain: this.config.cookieDomain,
|
|
605
|
+
path: this.config.cookiePath,
|
|
606
|
+
maxAge: this.config.jwtExpire * 1000,
|
|
607
|
+
secure: appUrl.protocol === 'https',
|
|
608
|
+
httpOnly: false,
|
|
609
|
+
sameSite: appUrl.protocol === 'https' ? 'lax' : 'strict',
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
if (sendAuthHeader) {
|
|
613
|
+
this.response.set('X-TILMELDAUTH', token);
|
|
614
|
+
}
|
|
616
615
|
}
|
|
616
|
+
this.response.locals.user = user;
|
|
617
617
|
}
|
|
618
618
|
this.fillSession(user);
|
|
619
619
|
return true;
|
|
620
620
|
}
|
|
621
621
|
return false;
|
|
622
622
|
}
|
|
623
|
-
|
|
623
|
+
loginSwitch(user, sendAuthHeader, sendCookie = true) {
|
|
624
|
+
if (user.guid != null) {
|
|
625
|
+
if (this.response) {
|
|
626
|
+
if (!this.response.headersSent) {
|
|
627
|
+
const token = this.config.jwtBuilder(this.config, user, true);
|
|
628
|
+
if (sendCookie) {
|
|
629
|
+
const appUrl = new url_1.URL(this.config.appUrl);
|
|
630
|
+
this.response.cookie('TILMELDSWITCH', token, {
|
|
631
|
+
domain: this.config.cookieDomain,
|
|
632
|
+
path: this.config.cookiePath,
|
|
633
|
+
maxAge: this.config.jwtSwitchExpire * 1000,
|
|
634
|
+
secure: appUrl.protocol === 'https',
|
|
635
|
+
httpOnly: false,
|
|
636
|
+
sameSite: appUrl.protocol === 'https' ? 'lax' : 'strict',
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
if (sendAuthHeader) {
|
|
640
|
+
this.response.set('X-TILMELDSWITCH', token);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
this.response.locals.user = user;
|
|
644
|
+
}
|
|
645
|
+
this.fillSession(user);
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
async logout(clearCookie = true) {
|
|
651
|
+
if (this.request && !this.alreadyLoggedOutSwitch) {
|
|
652
|
+
const cookies = this.request.cookies ?? {};
|
|
653
|
+
if ('TILMELDSWITCH' in cookies) {
|
|
654
|
+
this.alreadyLoggedOutSwitch = true;
|
|
655
|
+
return await this.logoutSwitch(clearCookie);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
624
658
|
this.clearSession();
|
|
625
|
-
if (this.response
|
|
626
|
-
this.response.
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
659
|
+
if (this.response) {
|
|
660
|
+
if (clearCookie && !this.response.headersSent) {
|
|
661
|
+
this.response.clearCookie('TILMELDAUTH', {
|
|
662
|
+
domain: this.config.cookieDomain,
|
|
663
|
+
path: this.config.cookiePath,
|
|
664
|
+
});
|
|
665
|
+
this.response.set('X-TILMELDAUTH', '');
|
|
666
|
+
}
|
|
667
|
+
this.response.locals.user = null;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
async logoutSwitch(clearCookie = true) {
|
|
671
|
+
this.clearSession();
|
|
672
|
+
if (this.response) {
|
|
673
|
+
if (clearCookie && !this.response.headersSent) {
|
|
674
|
+
this.response.clearCookie('TILMELDSWITCH', {
|
|
675
|
+
domain: this.config.cookieDomain,
|
|
676
|
+
path: this.config.cookiePath,
|
|
677
|
+
});
|
|
678
|
+
this.response.set('X-TILMELDSWITCH', '');
|
|
679
|
+
}
|
|
680
|
+
this.response.locals.user = null;
|
|
681
|
+
await this.authenticate();
|
|
631
682
|
}
|
|
632
683
|
}
|
|
633
684
|
}
|