@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/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.skipAuthenticate = false;
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
- class NymphUser extends User_1.default {
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
- NymphUser.nymph = this.nymph;
40
- NymphUser.tilmeld = this;
41
- NymphUser.skipOnClone = true;
42
- this.User = NymphUser;
43
- this.nymph.addEntityClass(NymphUser);
44
- class NymphGroup extends Group_1.default {
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.tilmeld;
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.gatekeeper('tilmeld/admin') &&
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.tilmeld;
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.driver.getEntitySync({ class: nymph.getEntityClass(className ?? 'Entity') }, { type: '&', guid: guid });
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.tilmeld;
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 (!aVal.$is(bVal)) {
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.map((entity) => entity.guid), bVal.map((entity) => entity.guid)).length) {
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 (((originalAc.user && !originalAc.user.$is(newAc.user)) ||
178
+ if ((originalAc.user && originalAc.user !== newAc.user) ||
193
179
  (!originalAc.user &&
194
180
  newAc.user &&
195
- !newAc.user.$is(tilmeld.currentUser))) &&
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
- !newAc.group.$is(originalAc.group) &&
201
- !(newAc.group.$is(tilmeld.currentUser?.group) ||
202
- newAc.group.$inArray(tilmeld.currentUser?.groups ?? [])) &&
203
- !tilmeld.gatekeeper('tilmeld/admin')) {
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.tilmeld;
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 != null &&
226
- user.group.guid != null) {
227
- entity.group = user.group;
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
- if (user.group != null && user.group.guid != null) {
348
- groupRefs.push(['group', user.group.guid]);
349
- acRefs.push(['acRead', user.group.guid]);
350
- acRefs.push(['acWrite', user.group.guid]);
351
- acRefs.push(['acFull', user.group.guid]);
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
- for (let curSecondaryGroup of user.groups ?? []) {
354
- if (curSecondaryGroup != null && curSecondaryGroup.guid != null) {
355
- groupRefs.push(['group', curSecondaryGroup.guid]);
356
- acRefs.push(['acRead', curSecondaryGroup.guid]);
357
- acRefs.push(['acWrite', curSecondaryGroup.guid]);
358
- acRefs.push(['acFull', curSecondaryGroup.guid]);
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 (typeof entity !== 'object' || typeof entity.$is !== 'function') {
402
- return false;
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.$gatekeeper('tilmeld/admin'))) {
420
- return true;
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 = entity.acUser ?? nymph_1.TilmeldAccessLevels.FULL_ACCESS;
426
- const acGroup = entity.acGroup ?? nymph_1.TilmeldAccessLevels.READ_ACCESS;
427
- const acOther = entity.acOther ?? nymph_1.TilmeldAccessLevels.NO_ACCESS;
428
- if (userOrNull === null) {
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
- if (userOrEmpty.group != null &&
435
- typeof userOrEmpty.group.$is === 'function' &&
436
- userOrEmpty.group.$is(entity) &&
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 allGroups = userOrEmpty.group == null ? [] : [userOrEmpty.group];
441
- allGroups = allGroups.concat(userOrEmpty.groups ?? []);
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: [...(entity.acFull ?? [])],
413
+ array: [...(acProperties.acFull ?? [])],
447
414
  },
448
415
  {
449
416
  type: nymph_1.TilmeldAccessLevels.WRITE_ACCESS,
450
- array: [...(entity.acWrite ?? [])],
417
+ array: [...(acProperties.acWrite ?? [])],
451
418
  },
452
419
  {
453
420
  type: nymph_1.TilmeldAccessLevels.READ_ACCESS,
454
- array: [...(entity.acRead ?? [])],
421
+ array: [...(acProperties.acRead ?? [])],
455
422
  },
456
423
  ];
457
424
  for (let curCheck of checks) {
458
425
  if (type <= curCheck.type) {
459
- if (userOrEmpty.$inArray(curCheck.array)) {
426
+ if (curCheck.array.includes(userOrEmpty.guid)) {
460
427
  return true;
461
428
  }
462
- for (let curGroup of allGroups) {
463
- if (typeof curGroup.$inArray === 'function' &&
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 (entity.user != null &&
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 (entity.group != null &&
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.$gatekeeper('system/admin')) {
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
- if (this.currentUser.group != null) {
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
- if (user.group != null) {
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 || !user.enabled) {
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 extract;
535
+ let authExtract;
536
+ let switchExtract;
572
537
  if (skipXsrfToken ||
573
538
  this.request.originalUrl.startsWith(this.config.setupPath)) {
574
- extract = this.config.jwtExtract(this.config, authToken);
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
- extract = this.config.jwtExtract(this.config, authToken, xsrfToken);
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 (extract == null) {
584
- this.logout();
554
+ if (authExtract == null) {
555
+ await this.logout();
585
556
  return false;
586
557
  }
587
- const { guid, expire } = extract;
588
- const user = this.User.factorySync(guid);
589
- if (user.guid == null || !user.enabled) {
590
- this.logout();
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 (expire.valueOf() < Date.now() + this.config.jwtRenew * 1000) {
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 && !this.response.headersSent) {
604
- const token = this.config.jwtBuilder(this.config, user);
605
- const appUrl = new url_1.URL(this.config.appUrl);
606
- this.response.cookie('TILMELDAUTH', token, {
607
- domain: this.config.cookieDomain,
608
- path: this.config.cookiePath,
609
- maxAge: this.config.jwtExpire * 1000,
610
- secure: appUrl.protocol === 'https',
611
- httpOnly: false,
612
- sameSite: appUrl.protocol === 'https' ? 'lax' : 'strict',
613
- });
614
- if (sendAuthHeader) {
615
- this.response.set('X-TILMELDAUTH', token);
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
- logout() {
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 && !this.response.headersSent) {
626
- this.response.clearCookie('TILMELDAUTH', {
627
- domain: this.config.cookieDomain,
628
- path: this.config.cookiePath,
629
- });
630
- this.response.set('X-TILMELDAUTH', '');
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
  }