@spinajs/session-provider-db 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.
@@ -1,17 +1,30 @@
1
- import { SessionProvider, ISession, User } from '@spinajs/rbac';
1
+ import { SessionProvider, ISession } from '@spinajs/rbac';
2
2
  import { Log } from '@spinajs/log';
3
3
  export * from './models/DbSession.js';
4
4
  export * from './migrations/UserSessionDBSqlMigration_2022_06_28_01_01_01.js';
5
+ /**
6
+ * Relational-db backed session store. Conforms to the `@spinajs/rbac`
7
+ * `SessionProvider` contract: ownership is the numeric `UserId`, expiration is
8
+ * owned by the injected strategy (`this.Expiration`) and persisted verbatim, and
9
+ * `Data` is (de)serialized with the shared session codec.
10
+ */
5
11
  export declare class DbSessionStore extends SessionProvider {
6
12
  protected Log: Log;
7
- protected CleanupInterval: any;
8
- protected DefaultExpirationTime: number;
13
+ /**
14
+ * How often expired rows are swept, in milliseconds. Reads the correctly
15
+ * spelled `rbac.session.db.cleanupInterval` key (fixes B2 — the historic typo
16
+ * `cleanupInteval` meant the configured value was ignored).
17
+ */
18
+ protected CleanupInterval: number;
9
19
  resolve(): Promise<void>;
10
20
  restore(sessionId: string): Promise<ISession | null>;
21
+ save(session: ISession): Promise<void>;
22
+ touch(session: ISession): Promise<boolean>;
11
23
  delete(sessionId: string): Promise<void>;
12
- save(sessionOrId: string | ISession, data?: object): Promise<void>;
13
- touch(session: ISession): Promise<void>;
14
- logsOut(user: User): Promise<void>;
24
+ deleteByUser(userId: number): Promise<void>;
25
+ listByUser(userId: number): Promise<ISession[]>;
15
26
  truncate(): Promise<void>;
27
+ private toSession;
28
+ private expirationEquals;
16
29
  }
17
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAe,IAAI,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAU,GAAG,EAAE,MAAM,cAAc,CAAC;AAQ3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+DAA+D,CAAC;AAE9E,qBACa,cAAe,SAAQ,eAAe;IAEjD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAKnB,SAAS,CAAC,eAAe,EAAE,GAAG,CAAC;IAG/B,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAE3B,OAAO;IAQP,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAuBpD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlE,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAqD,MAAM,eAAe,CAAC;AAE7G,OAAO,EAAU,GAAG,EAAE,MAAM,cAAc,CAAC;AAM3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+DAA+D,CAAC;AAE9E;;;;;GAKG;AACH,qBACa,cAAe,SAAQ,eAAe;IAEjD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB;;;;OAIG;IAIH,SAAS,CAAC,eAAe,EAAE,MAAM,CAAC;IAErB,OAAO;IAWP,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAmBpD,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBtC,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB1C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM/C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,gBAAgB;CAMzB"}
package/lib/cjs/index.js CHANGED
@@ -22,9 +22,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
22
22
  var __metadata = (this && this.__metadata) || function (k, v) {
23
23
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
24
24
  };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
25
  Object.defineProperty(exports, "__esModule", { value: true });
29
26
  exports.DbSessionStore = void 0;
30
27
  const rbac_1 = require("@spinajs/rbac");
@@ -34,67 +31,95 @@ const DbSession_js_1 = require("./models/DbSession.js");
34
31
  const orm_1 = require("@spinajs/orm");
35
32
  const configuration_1 = require("@spinajs/configuration");
36
33
  const luxon_1 = require("luxon");
37
- const lodash_1 = __importDefault(require("lodash"));
38
- const util_1 = require("@spinajs/util");
39
34
  __exportStar(require("./models/DbSession.js"), exports);
40
35
  __exportStar(require("./migrations/UserSessionDBSqlMigration_2022_06_28_01_01_01.js"), exports);
36
+ /**
37
+ * Relational-db backed session store. Conforms to the `@spinajs/rbac`
38
+ * `SessionProvider` contract: ownership is the numeric `UserId`, expiration is
39
+ * owned by the injected strategy (`this.Expiration`) and persisted verbatim, and
40
+ * `Data` is (de)serialized with the shared session codec.
41
+ */
41
42
  let DbSessionStore = class DbSessionStore extends rbac_1.SessionProvider {
42
43
  async resolve() {
43
- setInterval(async () => {
44
+ const timer = setInterval(async () => {
44
45
  const c = await DbSession_js_1.DbSession.destroy().where('Expiration', '<=', luxon_1.DateTime.now());
45
46
  this.Log.info(`Cleaned up expired session, count: ${c.RowsAffected}`);
46
47
  }, this.CleanupInterval);
48
+ // do not keep the process alive solely for the cleanup timer
49
+ timer.unref?.();
47
50
  }
48
51
  async restore(sessionId) {
49
- const session = await DbSession_js_1.DbSession.where({
52
+ const row = await DbSession_js_1.DbSession.where({
50
53
  SessionId: sessionId,
51
54
  }).first();
52
- if (!session) {
55
+ if (!row) {
53
56
  return null;
54
57
  }
55
- if (session.Expiration < luxon_1.DateTime.now()) {
58
+ const session = this.toSession(row);
59
+ // an expired row is treated as absent
60
+ if (this.isExpired(session)) {
56
61
  return null;
57
62
  }
58
- const sData = JSON.parse(session.Data);
59
- return new rbac_1.UserSession({
60
- SessionId: session.SessionId,
61
- Creation: session.CreatedAt,
62
- Data: new Map(Object.entries(sData)),
63
- Expiration: session.Expiration,
64
- });
65
- }
66
- async delete(sessionId) {
67
- await DbSession_js_1.DbSession.destroy(sessionId);
63
+ return session;
68
64
  }
69
- async save(sessionOrId, data) {
70
- const sessionId = lodash_1.default.isString(sessionOrId) ? sessionOrId : sessionOrId.SessionId;
71
- const userId = lodash_1.default.isString(sessionOrId) ? null : sessionOrId.UserId;
72
- const sData = lodash_1.default.isString(sessionOrId) ? data : sessionOrId.Data;
73
- let sCreationTime = luxon_1.DateTime.now();
74
- let sExpirationTime = luxon_1.DateTime.now().plus({ minutes: this.DefaultExpirationTime });
65
+ async save(session) {
66
+ // Persist `Expiration` verbatim (fixes B3). Only a brand-new session with no
67
+ // scheduled expiration is given its initial expiry via the strategy.
68
+ if (session.Expiration === undefined) {
69
+ this.applyInitialExpiration(session);
70
+ }
75
71
  const s = await DbSession_js_1.DbSession.getOrNew({
76
- SessionId: sessionId,
77
- CreatedAt: sCreationTime,
78
- Expiration: sExpirationTime,
79
- UserId: userId
72
+ SessionId: session.SessionId,
80
73
  });
81
- s.Data = JSON.stringify(Object.fromEntries(sData), util_1.replacer);
74
+ s.SessionId = session.SessionId;
75
+ s.CreatedAt = session.Creation;
76
+ // column is nullable; a never-expiring session persists a NULL Expiration
77
+ s.Expiration = (session.Expiration ?? null);
78
+ s.UserId = session.UserId;
79
+ s.Data = (0, rbac_1.encodeSessionData)(session.Data);
82
80
  await s.insert(orm_1.InsertBehaviour.InsertOrUpdate);
83
81
  }
84
82
  async touch(session) {
83
+ const current = session.Expiration;
84
+ const renewed = this.Expiration.renew(session);
85
+ // unchanged (e.g. AbsoluteExpiration) — skip the write, report false
86
+ if (this.expirationEquals(current, renewed)) {
87
+ return false;
88
+ }
89
+ session.Expiration = renewed;
85
90
  await DbSession_js_1.DbSession.update({
86
- Expiration: session.Expiration,
91
+ Expiration: renewed,
87
92
  }).where('SessionId', session.SessionId);
93
+ return true;
88
94
  }
89
- async logsOut(user) {
90
- const sessionsToDelete = await DbSession_js_1.DbSession.where('UserId', user.Id);
91
- if (sessionsToDelete.length > 0) {
92
- await DbSession_js_1.DbSession.destroy(sessionsToDelete.map((x) => x.SessionId));
93
- }
95
+ async delete(sessionId) {
96
+ await DbSession_js_1.DbSession.destroy(sessionId);
97
+ }
98
+ async deleteByUser(userId) {
99
+ await DbSession_js_1.DbSession.destroy().where('UserId', userId);
100
+ }
101
+ async listByUser(userId) {
102
+ const rows = await DbSession_js_1.DbSession.where('UserId', userId);
103
+ return rows.map((r) => this.toSession(r)).filter((s) => !this.isExpired(s));
94
104
  }
95
105
  async truncate() {
96
106
  await DbSession_js_1.DbSession.truncate();
97
107
  }
108
+ toSession(row) {
109
+ return new rbac_1.UserSession({
110
+ SessionId: row.SessionId,
111
+ UserId: row.UserId,
112
+ Creation: row.CreatedAt,
113
+ Expiration: row.Expiration ?? undefined,
114
+ Data: (0, rbac_1.decodeSessionData)(row.Data),
115
+ });
116
+ }
117
+ expirationEquals(a, b) {
118
+ if (a === undefined || b === undefined) {
119
+ return a === b;
120
+ }
121
+ return a.toMillis() === b.toMillis();
122
+ }
98
123
  };
99
124
  exports.DbSessionStore = DbSessionStore;
100
125
  __decorate([
@@ -102,15 +127,11 @@ __decorate([
102
127
  __metadata("design:type", log_1.Log)
103
128
  ], DbSessionStore.prototype, "Log", void 0);
104
129
  __decorate([
105
- (0, configuration_1.Config)('rbac.session.db.cleanupInteval', {
130
+ (0, configuration_1.Config)('rbac.session.db.cleanupInterval', {
106
131
  defaultValue: 100000,
107
132
  }),
108
- __metadata("design:type", Object)
109
- ], DbSessionStore.prototype, "CleanupInterval", void 0);
110
- __decorate([
111
- (0, configuration_1.Config)('rbac.session.expiration'),
112
133
  __metadata("design:type", Number)
113
- ], DbSessionStore.prototype, "DefaultExpirationTime", void 0);
134
+ ], DbSessionStore.prototype, "CleanupInterval", void 0);
114
135
  exports.DbSessionStore = DbSessionStore = __decorate([
115
136
  (0, di_1.Injectable)(rbac_1.SessionProvider)
116
137
  ], DbSessionStore);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,30 @@
1
- import { SessionProvider, ISession, User } from '@spinajs/rbac';
1
+ import { SessionProvider, ISession } from '@spinajs/rbac';
2
2
  import { Log } from '@spinajs/log';
3
3
  export * from './models/DbSession.js';
4
4
  export * from './migrations/UserSessionDBSqlMigration_2022_06_28_01_01_01.js';
5
+ /**
6
+ * Relational-db backed session store. Conforms to the `@spinajs/rbac`
7
+ * `SessionProvider` contract: ownership is the numeric `UserId`, expiration is
8
+ * owned by the injected strategy (`this.Expiration`) and persisted verbatim, and
9
+ * `Data` is (de)serialized with the shared session codec.
10
+ */
5
11
  export declare class DbSessionStore extends SessionProvider {
6
12
  protected Log: Log;
7
- protected CleanupInterval: any;
8
- protected DefaultExpirationTime: number;
13
+ /**
14
+ * How often expired rows are swept, in milliseconds. Reads the correctly
15
+ * spelled `rbac.session.db.cleanupInterval` key (fixes B2 — the historic typo
16
+ * `cleanupInteval` meant the configured value was ignored).
17
+ */
18
+ protected CleanupInterval: number;
9
19
  resolve(): Promise<void>;
10
20
  restore(sessionId: string): Promise<ISession | null>;
21
+ save(session: ISession): Promise<void>;
22
+ touch(session: ISession): Promise<boolean>;
11
23
  delete(sessionId: string): Promise<void>;
12
- save(sessionOrId: string | ISession, data?: object): Promise<void>;
13
- touch(session: ISession): Promise<void>;
14
- logsOut(user: User): Promise<void>;
24
+ deleteByUser(userId: number): Promise<void>;
25
+ listByUser(userId: number): Promise<ISession[]>;
15
26
  truncate(): Promise<void>;
27
+ private toSession;
28
+ private expirationEquals;
16
29
  }
17
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAe,IAAI,EAAE,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAU,GAAG,EAAE,MAAM,cAAc,CAAC;AAQ3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+DAA+D,CAAC;AAE9E,qBACa,cAAe,SAAQ,eAAe;IAEjD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAKnB,SAAS,CAAC,eAAe,EAAE,GAAG,CAAC;IAG/B,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAE3B,OAAO;IAQP,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAuBpD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlE,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAqD,MAAM,eAAe,CAAC;AAE7G,OAAO,EAAU,GAAG,EAAE,MAAM,cAAc,CAAC;AAM3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+DAA+D,CAAC;AAE9E;;;;;GAKG;AACH,qBACa,cAAe,SAAQ,eAAe;IAEjD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAEnB;;;;OAIG;IAIH,SAAS,CAAC,eAAe,EAAE,MAAM,CAAC;IAErB,OAAO;IAWP,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAmBpD,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBtC,KAAK,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAiB1C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM/C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,gBAAgB;CAMzB"}
package/lib/mjs/index.js CHANGED
@@ -7,89 +7,113 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- import { SessionProvider, UserSession } from '@spinajs/rbac';
10
+ import { SessionProvider, UserSession, encodeSessionData, decodeSessionData } from '@spinajs/rbac';
11
11
  import { Injectable } from '@spinajs/di';
12
12
  import { Logger, Log } from '@spinajs/log';
13
13
  import { DbSession } from './models/DbSession.js';
14
14
  import { InsertBehaviour } from '@spinajs/orm';
15
15
  import { Config } from '@spinajs/configuration';
16
16
  import { DateTime } from 'luxon';
17
- import _ from 'lodash';
18
- import { replacer } from '@spinajs/util';
19
17
  export * from './models/DbSession.js';
20
18
  export * from './migrations/UserSessionDBSqlMigration_2022_06_28_01_01_01.js';
19
+ /**
20
+ * Relational-db backed session store. Conforms to the `@spinajs/rbac`
21
+ * `SessionProvider` contract: ownership is the numeric `UserId`, expiration is
22
+ * owned by the injected strategy (`this.Expiration`) and persisted verbatim, and
23
+ * `Data` is (de)serialized with the shared session codec.
24
+ */
21
25
  let DbSessionStore = class DbSessionStore extends SessionProvider {
22
26
  async resolve() {
23
- setInterval(async () => {
27
+ const timer = setInterval(async () => {
24
28
  const c = await DbSession.destroy().where('Expiration', '<=', DateTime.now());
25
29
  this.Log.info(`Cleaned up expired session, count: ${c.RowsAffected}`);
26
30
  }, this.CleanupInterval);
31
+ // do not keep the process alive solely for the cleanup timer
32
+ timer.unref?.();
27
33
  }
28
34
  async restore(sessionId) {
29
- const session = await DbSession.where({
35
+ const row = await DbSession.where({
30
36
  SessionId: sessionId,
31
37
  }).first();
32
- if (!session) {
38
+ if (!row) {
33
39
  return null;
34
40
  }
35
- if (session.Expiration < DateTime.now()) {
41
+ const session = this.toSession(row);
42
+ // an expired row is treated as absent
43
+ if (this.isExpired(session)) {
36
44
  return null;
37
45
  }
38
- const sData = JSON.parse(session.Data);
39
- return new UserSession({
40
- SessionId: session.SessionId,
41
- Creation: session.CreatedAt,
42
- Data: new Map(Object.entries(sData)),
43
- Expiration: session.Expiration,
44
- });
45
- }
46
- async delete(sessionId) {
47
- await DbSession.destroy(sessionId);
46
+ return session;
48
47
  }
49
- async save(sessionOrId, data) {
50
- const sessionId = _.isString(sessionOrId) ? sessionOrId : sessionOrId.SessionId;
51
- const userId = _.isString(sessionOrId) ? null : sessionOrId.UserId;
52
- const sData = _.isString(sessionOrId) ? data : sessionOrId.Data;
53
- let sCreationTime = DateTime.now();
54
- let sExpirationTime = DateTime.now().plus({ minutes: this.DefaultExpirationTime });
48
+ async save(session) {
49
+ // Persist `Expiration` verbatim (fixes B3). Only a brand-new session with no
50
+ // scheduled expiration is given its initial expiry via the strategy.
51
+ if (session.Expiration === undefined) {
52
+ this.applyInitialExpiration(session);
53
+ }
55
54
  const s = await DbSession.getOrNew({
56
- SessionId: sessionId,
57
- CreatedAt: sCreationTime,
58
- Expiration: sExpirationTime,
59
- UserId: userId
55
+ SessionId: session.SessionId,
60
56
  });
61
- s.Data = JSON.stringify(Object.fromEntries(sData), replacer);
57
+ s.SessionId = session.SessionId;
58
+ s.CreatedAt = session.Creation;
59
+ // column is nullable; a never-expiring session persists a NULL Expiration
60
+ s.Expiration = (session.Expiration ?? null);
61
+ s.UserId = session.UserId;
62
+ s.Data = encodeSessionData(session.Data);
62
63
  await s.insert(InsertBehaviour.InsertOrUpdate);
63
64
  }
64
65
  async touch(session) {
66
+ const current = session.Expiration;
67
+ const renewed = this.Expiration.renew(session);
68
+ // unchanged (e.g. AbsoluteExpiration) — skip the write, report false
69
+ if (this.expirationEquals(current, renewed)) {
70
+ return false;
71
+ }
72
+ session.Expiration = renewed;
65
73
  await DbSession.update({
66
- Expiration: session.Expiration,
74
+ Expiration: renewed,
67
75
  }).where('SessionId', session.SessionId);
76
+ return true;
68
77
  }
69
- async logsOut(user) {
70
- const sessionsToDelete = await DbSession.where('UserId', user.Id);
71
- if (sessionsToDelete.length > 0) {
72
- await DbSession.destroy(sessionsToDelete.map((x) => x.SessionId));
73
- }
78
+ async delete(sessionId) {
79
+ await DbSession.destroy(sessionId);
80
+ }
81
+ async deleteByUser(userId) {
82
+ await DbSession.destroy().where('UserId', userId);
83
+ }
84
+ async listByUser(userId) {
85
+ const rows = await DbSession.where('UserId', userId);
86
+ return rows.map((r) => this.toSession(r)).filter((s) => !this.isExpired(s));
74
87
  }
75
88
  async truncate() {
76
89
  await DbSession.truncate();
77
90
  }
91
+ toSession(row) {
92
+ return new UserSession({
93
+ SessionId: row.SessionId,
94
+ UserId: row.UserId,
95
+ Creation: row.CreatedAt,
96
+ Expiration: row.Expiration ?? undefined,
97
+ Data: decodeSessionData(row.Data),
98
+ });
99
+ }
100
+ expirationEquals(a, b) {
101
+ if (a === undefined || b === undefined) {
102
+ return a === b;
103
+ }
104
+ return a.toMillis() === b.toMillis();
105
+ }
78
106
  };
79
107
  __decorate([
80
108
  Logger('db-session-store'),
81
109
  __metadata("design:type", Log)
82
110
  ], DbSessionStore.prototype, "Log", void 0);
83
111
  __decorate([
84
- Config('rbac.session.db.cleanupInteval', {
112
+ Config('rbac.session.db.cleanupInterval', {
85
113
  defaultValue: 100000,
86
114
  }),
87
- __metadata("design:type", Object)
88
- ], DbSessionStore.prototype, "CleanupInterval", void 0);
89
- __decorate([
90
- Config('rbac.session.expiration'),
91
115
  __metadata("design:type", Number)
92
- ], DbSessionStore.prototype, "DefaultExpirationTime", void 0);
116
+ ], DbSessionStore.prototype, "CleanupInterval", void 0);
93
117
  DbSessionStore = __decorate([
94
118
  Injectable(SessionProvider)
95
119
  ], DbSessionStore);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}