@spinajs/rbac 2.0.480 → 2.0.482

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.
Files changed (93) hide show
  1. package/lib/cjs/actions.d.ts.map +1 -1
  2. package/lib/cjs/actions.js +32 -6
  3. package/lib/cjs/actions.js.map +1 -1
  4. package/lib/cjs/cli/ActivateUser.js +1 -1
  5. package/lib/cjs/cli/ActivateUser.js.map +1 -1
  6. package/lib/cjs/cli/BanUser.js +1 -1
  7. package/lib/cjs/cli/BanUser.js.map +1 -1
  8. package/lib/cjs/config/rbac.d.ts +11 -1
  9. package/lib/cjs/config/rbac.d.ts.map +1 -1
  10. package/lib/cjs/config/rbac.js +12 -3
  11. package/lib/cjs/config/rbac.js.map +1 -1
  12. package/lib/cjs/cron/DeactivatePasswords.d.ts.map +1 -1
  13. package/lib/cjs/cron/DeactivatePasswords.js +6 -2
  14. package/lib/cjs/cron/DeactivatePasswords.js.map +1 -1
  15. package/lib/cjs/index.d.ts +6 -0
  16. package/lib/cjs/index.d.ts.map +1 -1
  17. package/lib/cjs/index.js +6 -0
  18. package/lib/cjs/index.js.map +1 -1
  19. package/lib/cjs/interfaces.d.ts +63 -37
  20. package/lib/cjs/interfaces.d.ts.map +1 -1
  21. package/lib/cjs/interfaces.js +43 -1
  22. package/lib/cjs/interfaces.js.map +1 -1
  23. package/lib/cjs/middleware.d.ts +23 -1
  24. package/lib/cjs/middleware.d.ts.map +1 -1
  25. package/lib/cjs/middleware.js +158 -104
  26. package/lib/cjs/middleware.js.map +1 -1
  27. package/lib/cjs/models/User.d.ts.map +1 -1
  28. package/lib/cjs/models/User.js +15 -1
  29. package/lib/cjs/models/User.js.map +1 -1
  30. package/lib/cjs/ownership.d.ts +2 -0
  31. package/lib/cjs/ownership.d.ts.map +1 -0
  32. package/lib/cjs/ownership.js +46 -0
  33. package/lib/cjs/ownership.js.map +1 -0
  34. package/lib/cjs/session-codec.d.ts +15 -0
  35. package/lib/cjs/session-codec.d.ts.map +1 -0
  36. package/lib/cjs/session-codec.js +59 -0
  37. package/lib/cjs/session-codec.js.map +1 -0
  38. package/lib/cjs/session-expiration.d.ts +40 -0
  39. package/lib/cjs/session-expiration.d.ts.map +1 -0
  40. package/lib/cjs/session-expiration.js +93 -0
  41. package/lib/cjs/session-expiration.js.map +1 -0
  42. package/lib/cjs/session.d.ts +38 -18
  43. package/lib/cjs/session.d.ts.map +1 -1
  44. package/lib/cjs/session.js +91 -50
  45. package/lib/cjs/session.js.map +1 -1
  46. package/lib/mjs/actions.d.ts.map +1 -1
  47. package/lib/mjs/actions.js +32 -6
  48. package/lib/mjs/actions.js.map +1 -1
  49. package/lib/mjs/cli/ActivateUser.js +1 -1
  50. package/lib/mjs/cli/ActivateUser.js.map +1 -1
  51. package/lib/mjs/cli/BanUser.js +1 -1
  52. package/lib/mjs/cli/BanUser.js.map +1 -1
  53. package/lib/mjs/config/rbac.d.ts +11 -1
  54. package/lib/mjs/config/rbac.d.ts.map +1 -1
  55. package/lib/mjs/config/rbac.js +12 -3
  56. package/lib/mjs/config/rbac.js.map +1 -1
  57. package/lib/mjs/cron/DeactivatePasswords.d.ts.map +1 -1
  58. package/lib/mjs/cron/DeactivatePasswords.js +6 -2
  59. package/lib/mjs/cron/DeactivatePasswords.js.map +1 -1
  60. package/lib/mjs/index.d.ts +6 -0
  61. package/lib/mjs/index.d.ts.map +1 -1
  62. package/lib/mjs/index.js +6 -0
  63. package/lib/mjs/index.js.map +1 -1
  64. package/lib/mjs/interfaces.d.ts +63 -37
  65. package/lib/mjs/interfaces.d.ts.map +1 -1
  66. package/lib/mjs/interfaces.js +41 -0
  67. package/lib/mjs/interfaces.js.map +1 -1
  68. package/lib/mjs/middleware.d.ts +23 -1
  69. package/lib/mjs/middleware.d.ts.map +1 -1
  70. package/lib/mjs/middleware.js +158 -104
  71. package/lib/mjs/middleware.js.map +1 -1
  72. package/lib/mjs/models/User.d.ts.map +1 -1
  73. package/lib/mjs/models/User.js +15 -1
  74. package/lib/mjs/models/User.js.map +1 -1
  75. package/lib/mjs/ownership.d.ts +2 -0
  76. package/lib/mjs/ownership.d.ts.map +1 -0
  77. package/lib/mjs/ownership.js +44 -0
  78. package/lib/mjs/ownership.js.map +1 -0
  79. package/lib/mjs/session-codec.d.ts +15 -0
  80. package/lib/mjs/session-codec.d.ts.map +1 -0
  81. package/lib/mjs/session-codec.js +55 -0
  82. package/lib/mjs/session-codec.js.map +1 -0
  83. package/lib/mjs/session-expiration.d.ts +40 -0
  84. package/lib/mjs/session-expiration.d.ts.map +1 -0
  85. package/lib/mjs/session-expiration.js +90 -0
  86. package/lib/mjs/session-expiration.js.map +1 -0
  87. package/lib/mjs/session.d.ts +38 -18
  88. package/lib/mjs/session.d.ts.map +1 -1
  89. package/lib/mjs/session.js +89 -47
  90. package/lib/mjs/session.js.map +1 -1
  91. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  92. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  93. package/package.json +15 -12
@@ -0,0 +1,90 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DateTime } from 'luxon';
11
+ import { Injectable } from '@spinajs/di';
12
+ import { Config } from '@spinajs/configuration';
13
+ import { SessionExpirationProvider } from './interfaces.js';
14
+ /**
15
+ * Absolute expiration: the session dies at a fixed instant from creation and is
16
+ * never extended. `touch` is therefore a no-op (renew returns the current
17
+ * Expiration unchanged).
18
+ *
19
+ * Settings: `rbac.session.expiration.ttl` (minutes).
20
+ */
21
+ let AbsoluteExpiration = class AbsoluteExpiration extends SessionExpirationProvider {
22
+ initial(session) {
23
+ return session.Creation.plus({ minutes: this.Ttl });
24
+ }
25
+ renew(session) {
26
+ // no slide — keep whatever absolute instant was set at creation
27
+ return session.Expiration;
28
+ }
29
+ };
30
+ __decorate([
31
+ Config('rbac.session.expiration.ttl', { defaultValue: 120 }),
32
+ __metadata("design:type", Number)
33
+ ], AbsoluteExpiration.prototype, "Ttl", void 0);
34
+ AbsoluteExpiration = __decorate([
35
+ Injectable(SessionExpirationProvider)
36
+ ], AbsoluteExpiration);
37
+ export { AbsoluteExpiration };
38
+ /**
39
+ * Sliding expiration: every renewal pushes the expiration to `now + ttl`, with
40
+ * no upper bound. Activity keeps the session alive indefinitely.
41
+ *
42
+ * Settings: `rbac.session.expiration.ttl` (minutes).
43
+ */
44
+ let SlidingExpiration = class SlidingExpiration extends SessionExpirationProvider {
45
+ initial(_session) {
46
+ return DateTime.now().plus({ minutes: this.Ttl });
47
+ }
48
+ renew(_session) {
49
+ return DateTime.now().plus({ minutes: this.Ttl });
50
+ }
51
+ };
52
+ __decorate([
53
+ Config('rbac.session.expiration.ttl', { defaultValue: 120 }),
54
+ __metadata("design:type", Number)
55
+ ], SlidingExpiration.prototype, "Ttl", void 0);
56
+ SlidingExpiration = __decorate([
57
+ Injectable(SessionExpirationProvider)
58
+ ], SlidingExpiration);
59
+ export { SlidingExpiration };
60
+ /**
61
+ * Sliding expiration with an absolute cap: renewal pushes the expiration to
62
+ * `now + ttl` but never past `Creation + maxLifetime`. Combines idle timeout
63
+ * with a hard session lifetime ceiling.
64
+ *
65
+ * Settings: `rbac.session.expiration.ttl` and
66
+ * `rbac.session.expiration.maxLifetime` (both minutes).
67
+ */
68
+ let SlidingCappedExpiration = class SlidingCappedExpiration extends SessionExpirationProvider {
69
+ initial(_session) {
70
+ return DateTime.now().plus({ minutes: this.Ttl });
71
+ }
72
+ renew(session) {
73
+ const slide = DateTime.now().plus({ minutes: this.Ttl });
74
+ const cap = session.Creation.plus({ minutes: this.MaxLifetime });
75
+ return slide < cap ? slide : cap;
76
+ }
77
+ };
78
+ __decorate([
79
+ Config('rbac.session.expiration.ttl', { defaultValue: 120 }),
80
+ __metadata("design:type", Number)
81
+ ], SlidingCappedExpiration.prototype, "Ttl", void 0);
82
+ __decorate([
83
+ Config('rbac.session.expiration.maxLifetime', { defaultValue: 1440 }),
84
+ __metadata("design:type", Number)
85
+ ], SlidingCappedExpiration.prototype, "MaxLifetime", void 0);
86
+ SlidingCappedExpiration = __decorate([
87
+ Injectable(SessionExpirationProvider)
88
+ ], SlidingCappedExpiration);
89
+ export { SlidingCappedExpiration };
90
+ //# sourceMappingURL=session-expiration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-expiration.js","sourceRoot":"","sources":["../../src/session-expiration.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAY,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAEtE;;;;;;GAMG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,yBAAyB;IAIxD,OAAO,CAAC,OAAiB;QAC9B,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,CAAC;IAEM,KAAK,CAAC,OAAiB;QAC5B,gEAAgE;QAChE,OAAO,OAAO,CAAC,UAAU,CAAC;IAC5B,CAAC;CACF,CAAA;AAVW;IADT,MAAM,CAAC,6BAA6B,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;+CACtC;AAFZ,kBAAkB;IAD9B,UAAU,CAAC,yBAAyB,CAAC;GACzB,kBAAkB,CAY9B;;AAED;;;;;GAKG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAkB,SAAQ,yBAAyB;IAIvD,OAAO,CAAC,QAAkB;QAC/B,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IAEM,KAAK,CAAC,QAAkB;QAC7B,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAA;AATW;IADT,MAAM,CAAC,6BAA6B,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;8CACtC;AAFZ,iBAAiB;IAD7B,UAAU,CAAC,yBAAyB,CAAC;GACzB,iBAAiB,CAW7B;;AAED;;;;;;;GAOG;AAEI,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,yBAAyB;IAO7D,OAAO,CAAC,QAAkB;QAC/B,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IAEM,KAAK,CAAC,OAAiB;QAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACjE,OAAO,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IACnC,CAAC;CACF,CAAA;AAdW;IADT,MAAM,CAAC,6BAA6B,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;;oDACtC;AAGb;IADT,MAAM,CAAC,qCAAqC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;;4DACvC;AALpB,uBAAuB;IADnC,UAAU,CAAC,yBAAyB,CAAC;GACzB,uBAAuB,CAgBnC"}
@@ -1,40 +1,60 @@
1
1
  import { DateTime } from 'luxon';
2
2
  import { SessionProvider, ISession } from './interfaces.js';
3
- import { User } from './models/User.js';
4
3
  /**
5
4
  * Session base class
6
5
  */
7
6
  export declare class UserSession implements ISession {
8
- protected SessionExpirationTime: number;
9
7
  SessionId: string;
10
8
  /**
11
- * Expiration time for session, if null it does not expire
9
+ * User id that owns this session. Single source of truth for ownership.
12
10
  */
13
- Expiration: DateTime | undefined;
14
- Data: Map<string, unknown>;
11
+ UserId: number;
15
12
  Creation: DateTime;
16
13
  /**
17
- * User id that owns this session
14
+ * Expiration time for session, if undefined it does not expire.
15
+ * Set by the SessionProvider through the configured expiration strategy.
18
16
  */
19
- UserId: number;
17
+ Expiration: DateTime | undefined;
18
+ Data: Map<string, unknown>;
20
19
  constructor(session?: Partial<ISession>);
21
- /**
22
- * Extends lifetime of session
23
- *
24
- * @param seconds - hom mutch to extend
25
- */
26
- extend(seconds?: number): void;
27
20
  }
28
21
  /**
29
- * Simple session storage in memory, for testing or rapid prototyping
22
+ * Derives the `ssid` cookie `maxAge` (milliseconds) from a session's real
23
+ * `Expiration` (fixes B1 — the cookie previously always died at
24
+ * `expiration * 1000` ms i.e. ~2 minutes). Returns `undefined` for a
25
+ * never-expiring session (a session cookie), and never a negative value.
26
+ *
27
+ * @param session - the session whose expiry drives the cookie lifetime
28
+ */
29
+ export declare function sessionCookieMaxAge(session: ISession): number | undefined;
30
+ /**
31
+ * Session-fixation protection helper. Mints a NEW session id, copies the
32
+ * ownership identity and data across, deletes the old id and persists the new
33
+ * one. Apply on privilege elevation (login already mints a fresh session, but
34
+ * 2FA-authorize and role-switch elevate an existing one).
35
+ *
36
+ * The returned session carries a new `SessionId` so the caller can reset the
37
+ * `ssid` cookie. `Expiration` is left unset so `save` schedules a fresh one via
38
+ * the configured strategy (`Creation` is preserved, so a capped lifetime window
39
+ * is not extended).
40
+ *
41
+ * @param provider - the active session store
42
+ * @param session - the session to regenerate
43
+ */
44
+ export declare function regenerateSession(provider: SessionProvider, session: ISession): Promise<ISession>;
45
+ /**
46
+ * Simple session storage in memory, for testing or rapid prototyping.
47
+ * Keeps live session objects (no serialization).
30
48
  */
31
49
  export declare class MemorySessionStore extends SessionProvider<ISession> {
32
50
  protected Sessions: Map<string, ISession>;
33
- truncate(): Promise<void>;
34
- touch(session: ISession): Promise<void>;
35
51
  restore(sessionId: string): Promise<ISession | null>;
52
+ save(session: ISession): Promise<void>;
53
+ touch(session: ISession): Promise<boolean>;
36
54
  delete(sessionId: string): Promise<void>;
37
- save(idOrSession: ISession | string, data?: object): Promise<void>;
38
- logsOut(user: User): Promise<void>;
55
+ deleteByUser(userId: number): Promise<void>;
56
+ listByUser(userId: number): Promise<ISession[]>;
57
+ truncate(): Promise<void>;
58
+ private expirationEquals;
39
59
  }
40
60
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAK5D,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;GAEG;AACH,qBACa,WAAY,YAAW,QAAQ;IAE1C,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAEjC,SAAS,EAAE,MAAM,CAAY;IAEpC;;OAEG;IACI,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAa;IAE7C,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;IAEvC,QAAQ,EAAE,QAAQ,CAAkB;IAE3C;;OAEG;IACI,MAAM,EAAE,MAAM,CAAC;gBAEV,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;IAMvC;;;;OAIG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM;CAG/B;AAED;;GAEG;AACH,qBACa,kBAAmB,SAAQ,eAAe,CAAC,QAAQ,CAAC;IAE/D,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAA+B;IAE3D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAYpD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxE,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAgB1C"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAI5D;;GAEG;AACH,qBACa,WAAY,YAAW,QAAQ;IACnC,SAAS,EAAE,MAAM,CAAY;IAEpC;;OAEG;IACI,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,QAAQ,CAAkB;IAE3C;;;OAGG;IACI,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAa;IAE7C,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;gBAElC,OAAO,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;CAKxC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAWvG;AAED;;;GAGG;AACH,qBACa,kBAAmB,SAAQ,eAAe,CAAC,QAAQ,CAAC;IAC/D,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAA+B;IAE3D,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAepD,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWtC,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAc1C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAU/C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,OAAO,CAAC,gBAAgB;CAMzB"}
@@ -10,94 +10,136 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  import { DateTime } from 'luxon';
11
11
  import { SessionProvider } from './interfaces.js';
12
12
  import { Injectable, NewInstance } from '@spinajs/di';
13
- import { Config } from '@spinajs/configuration';
14
13
  import { v4 as uuidv4 } from 'uuid';
15
- import _ from 'lodash';
16
14
  /**
17
15
  * Session base class
18
16
  */
19
17
  let UserSession = class UserSession {
20
18
  constructor(session) {
21
19
  this.SessionId = uuidv4();
20
+ this.Creation = DateTime.now();
22
21
  /**
23
- * Expiration time for session, if null it does not expire
22
+ * Expiration time for session, if undefined it does not expire.
23
+ * Set by the SessionProvider through the configured expiration strategy.
24
24
  */
25
25
  this.Expiration = undefined;
26
26
  this.Data = new Map();
27
- this.Creation = DateTime.now();
28
27
  if (session) {
29
28
  Object.assign(this, session);
30
29
  }
31
30
  }
32
- /**
33
- * Extends lifetime of session
34
- *
35
- * @param seconds - hom mutch to extend
36
- */
37
- extend(seconds) {
38
- this.Expiration = DateTime.now().plus({ seconds: seconds ? seconds : this.SessionExpirationTime });
39
- }
40
31
  };
41
- __decorate([
42
- Config('rbac.session.expiration'),
43
- __metadata("design:type", Number)
44
- ], UserSession.prototype, "SessionExpirationTime", void 0);
45
32
  UserSession = __decorate([
46
33
  NewInstance(),
47
34
  __metadata("design:paramtypes", [Object])
48
35
  ], UserSession);
49
36
  export { UserSession };
50
37
  /**
51
- * Simple session storage in memory, for testing or rapid prototyping
38
+ * Derives the `ssid` cookie `maxAge` (milliseconds) from a session's real
39
+ * `Expiration` (fixes B1 — the cookie previously always died at
40
+ * `expiration * 1000` ms i.e. ~2 minutes). Returns `undefined` for a
41
+ * never-expiring session (a session cookie), and never a negative value.
42
+ *
43
+ * @param session - the session whose expiry drives the cookie lifetime
44
+ */
45
+ export function sessionCookieMaxAge(session) {
46
+ if (!session.Expiration) {
47
+ return undefined;
48
+ }
49
+ return Math.max(0, Math.floor(session.Expiration.diff(DateTime.now()).milliseconds));
50
+ }
51
+ /**
52
+ * Session-fixation protection helper. Mints a NEW session id, copies the
53
+ * ownership identity and data across, deletes the old id and persists the new
54
+ * one. Apply on privilege elevation (login already mints a fresh session, but
55
+ * 2FA-authorize and role-switch elevate an existing one).
56
+ *
57
+ * The returned session carries a new `SessionId` so the caller can reset the
58
+ * `ssid` cookie. `Expiration` is left unset so `save` schedules a fresh one via
59
+ * the configured strategy (`Creation` is preserved, so a capped lifetime window
60
+ * is not extended).
61
+ *
62
+ * @param provider - the active session store
63
+ * @param session - the session to regenerate
64
+ */
65
+ export async function regenerateSession(provider, session) {
66
+ const regenerated = new UserSession({
67
+ UserId: session.UserId,
68
+ Creation: session.Creation,
69
+ Data: new Map(session.Data),
70
+ });
71
+ await provider.delete(session.SessionId);
72
+ await provider.save(regenerated);
73
+ return regenerated;
74
+ }
75
+ /**
76
+ * Simple session storage in memory, for testing or rapid prototyping.
77
+ * Keeps live session objects (no serialization).
52
78
  */
53
79
  let MemorySessionStore = class MemorySessionStore extends SessionProvider {
54
80
  constructor() {
55
81
  super(...arguments);
56
82
  this.Sessions = new Map();
57
83
  }
58
- async truncate() {
59
- this.Sessions = new Map();
60
- }
61
- async touch(session) {
62
- return this.save(session);
63
- }
64
84
  async restore(sessionId) {
65
- if (this.Sessions.has(sessionId)) {
66
- const session = this.Sessions.get(sessionId);
67
- if (!session.Expiration || session.Expiration > DateTime.now()) {
68
- return session;
69
- }
85
+ const session = this.Sessions.get(sessionId);
86
+ if (!session) {
70
87
  return null;
71
88
  }
72
- return null;
73
- }
74
- async delete(sessionId) {
75
- if (this.Sessions.has(sessionId)) {
89
+ // an expired row is treated as absent (and evicted)
90
+ if (this.isExpired(session)) {
76
91
  this.Sessions.delete(sessionId);
92
+ return null;
77
93
  }
94
+ return session;
78
95
  }
79
- async save(idOrSession, data) {
80
- if (_.isString(idOrSession)) {
81
- const s = this.Sessions.get(idOrSession);
82
- for (const key in data) {
83
- s.Data.set(key, data[key]);
84
- }
96
+ async save(session) {
97
+ // A brand-new session without a scheduled expiration gets its initial
98
+ // expiration from the strategy. An already-scheduled expiration is
99
+ // persisted verbatim (fixes B3 never recompute on every save).
100
+ if (session.Expiration === undefined) {
101
+ this.applyInitialExpiration(session);
85
102
  }
86
- else {
87
- this.Sessions.set(idOrSession.SessionId, idOrSession);
103
+ this.Sessions.set(session.SessionId, session);
104
+ }
105
+ async touch(session) {
106
+ const current = session.Expiration;
107
+ const renewed = this.Expiration.renew(session);
108
+ // no change (e.g. AbsoluteExpiration) — skip the write, report false
109
+ if (this.expirationEquals(current, renewed)) {
110
+ return false;
88
111
  }
112
+ session.Expiration = renewed;
113
+ this.Sessions.set(session.SessionId, session);
114
+ return true;
115
+ }
116
+ async delete(sessionId) {
117
+ this.Sessions.delete(sessionId);
89
118
  }
90
- logsOut(user) {
91
- const sessionsToDelete = [];
119
+ async deleteByUser(userId) {
92
120
  for (const [key, session] of this.Sessions.entries()) {
93
- if (session.UserId === user.Id) {
94
- sessionsToDelete.push(key);
121
+ if (session.UserId === userId) {
122
+ this.Sessions.delete(key);
95
123
  }
96
124
  }
97
- for (const sessionId of sessionsToDelete) {
98
- this.Sessions.delete(sessionId);
125
+ }
126
+ async listByUser(userId) {
127
+ const result = [];
128
+ for (const session of this.Sessions.values()) {
129
+ if (session.UserId === userId && !this.isExpired(session)) {
130
+ result.push(session);
131
+ }
132
+ }
133
+ return result;
134
+ }
135
+ async truncate() {
136
+ this.Sessions = new Map();
137
+ }
138
+ expirationEquals(a, b) {
139
+ if (a === undefined || b === undefined) {
140
+ return a === b;
99
141
  }
100
- return Promise.resolve();
142
+ return a.toMillis() === b.toMillis();
101
143
  }
102
144
  };
103
145
  MemorySessionStore = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}