@spinajs/rbac-http-user 2.0.473 → 2.0.474

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 (75) hide show
  1. package/lib/cjs/controllers/ActiveRoleController.d.ts +41 -0
  2. package/lib/cjs/controllers/ActiveRoleController.d.ts.map +1 -0
  3. package/lib/cjs/controllers/ActiveRoleController.js +135 -0
  4. package/lib/cjs/controllers/ActiveRoleController.js.map +1 -0
  5. package/lib/cjs/controllers/ImpersonationController.d.ts +72 -0
  6. package/lib/cjs/controllers/ImpersonationController.d.ts.map +1 -0
  7. package/lib/cjs/controllers/ImpersonationController.js +277 -0
  8. package/lib/cjs/controllers/ImpersonationController.js.map +1 -0
  9. package/lib/cjs/controllers/LoginController.d.ts +27 -4
  10. package/lib/cjs/controllers/LoginController.d.ts.map +1 -1
  11. package/lib/cjs/controllers/LoginController.js +46 -27
  12. package/lib/cjs/controllers/LoginController.js.map +1 -1
  13. package/lib/cjs/dto/impersonate-dto.d.ts +24 -0
  14. package/lib/cjs/dto/impersonate-dto.d.ts.map +1 -0
  15. package/lib/cjs/dto/impersonate-dto.js +34 -0
  16. package/lib/cjs/dto/impersonate-dto.js.map +1 -0
  17. package/lib/cjs/dto/switchRole-dto.d.ts +24 -0
  18. package/lib/cjs/dto/switchRole-dto.d.ts.map +1 -0
  19. package/lib/cjs/dto/switchRole-dto.js +34 -0
  20. package/lib/cjs/dto/switchRole-dto.js.map +1 -0
  21. package/lib/cjs/handlers/DefaultLogoutHandler.d.ts +14 -0
  22. package/lib/cjs/handlers/DefaultLogoutHandler.d.ts.map +1 -0
  23. package/lib/cjs/handlers/DefaultLogoutHandler.js +61 -0
  24. package/lib/cjs/handlers/DefaultLogoutHandler.js.map +1 -0
  25. package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts +18 -0
  26. package/lib/cjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -0
  27. package/lib/cjs/handlers/ImpersonationLogoutHandler.js +66 -0
  28. package/lib/cjs/handlers/ImpersonationLogoutHandler.js.map +1 -0
  29. package/lib/cjs/index.d.ts +5 -0
  30. package/lib/cjs/index.d.ts.map +1 -1
  31. package/lib/cjs/index.js +5 -0
  32. package/lib/cjs/index.js.map +1 -1
  33. package/lib/cjs/logout.d.ts +51 -0
  34. package/lib/cjs/logout.d.ts.map +1 -0
  35. package/lib/cjs/logout.js +29 -0
  36. package/lib/cjs/logout.js.map +1 -0
  37. package/lib/mjs/controllers/ActiveRoleController.d.ts +41 -0
  38. package/lib/mjs/controllers/ActiveRoleController.d.ts.map +1 -0
  39. package/lib/mjs/controllers/ActiveRoleController.js +132 -0
  40. package/lib/mjs/controllers/ActiveRoleController.js.map +1 -0
  41. package/lib/mjs/controllers/ImpersonationController.d.ts +72 -0
  42. package/lib/mjs/controllers/ImpersonationController.d.ts.map +1 -0
  43. package/lib/mjs/controllers/ImpersonationController.js +274 -0
  44. package/lib/mjs/controllers/ImpersonationController.js.map +1 -0
  45. package/lib/mjs/controllers/LoginController.d.ts +27 -4
  46. package/lib/mjs/controllers/LoginController.d.ts.map +1 -1
  47. package/lib/mjs/controllers/LoginController.js +48 -29
  48. package/lib/mjs/controllers/LoginController.js.map +1 -1
  49. package/lib/mjs/dto/impersonate-dto.d.ts +24 -0
  50. package/lib/mjs/dto/impersonate-dto.d.ts.map +1 -0
  51. package/lib/mjs/dto/impersonate-dto.js +31 -0
  52. package/lib/mjs/dto/impersonate-dto.js.map +1 -0
  53. package/lib/mjs/dto/switchRole-dto.d.ts +24 -0
  54. package/lib/mjs/dto/switchRole-dto.d.ts.map +1 -0
  55. package/lib/mjs/dto/switchRole-dto.js +31 -0
  56. package/lib/mjs/dto/switchRole-dto.js.map +1 -0
  57. package/lib/mjs/handlers/DefaultLogoutHandler.d.ts +14 -0
  58. package/lib/mjs/handlers/DefaultLogoutHandler.d.ts.map +1 -0
  59. package/lib/mjs/handlers/DefaultLogoutHandler.js +58 -0
  60. package/lib/mjs/handlers/DefaultLogoutHandler.js.map +1 -0
  61. package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts +18 -0
  62. package/lib/mjs/handlers/ImpersonationLogoutHandler.d.ts.map +1 -0
  63. package/lib/mjs/handlers/ImpersonationLogoutHandler.js +63 -0
  64. package/lib/mjs/handlers/ImpersonationLogoutHandler.js.map +1 -0
  65. package/lib/mjs/index.d.ts +5 -0
  66. package/lib/mjs/index.d.ts.map +1 -1
  67. package/lib/mjs/index.js +5 -0
  68. package/lib/mjs/index.js.map +1 -1
  69. package/lib/mjs/logout.d.ts +51 -0
  70. package/lib/mjs/logout.d.ts.map +1 -0
  71. package/lib/mjs/logout.js +25 -0
  72. package/lib/mjs/logout.js.map +1 -0
  73. package/lib/tsconfig.cjs.tsbuildinfo +1 -1
  74. package/lib/tsconfig.mjs.tsbuildinfo +1 -1
  75. package/package.json +11 -11
@@ -13,10 +13,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  import { UserLoginDto } from '../dto/userLogin-dto.js';
14
14
  import { BaseController, BasePath, Post, Body, Ok, Get, Cookie, Unauthorized, Policy } from '@spinajs/http';
15
15
  import { AuthProvider, SessionProvider, login, UserSession, AccessControl, _unwindGrants } from '@spinajs/rbac';
16
- import { Autoinject } from '@spinajs/di';
16
+ import { Autoinject, DI } from '@spinajs/di';
17
17
  import { AutoinjectService, Config, Configuration } from '@spinajs/configuration';
18
- import { LoggedPolicy, User as UserRouteArg } from '@spinajs/rbac-http';
18
+ import { LoggedPolicy, User as UserRouteArg, Session as SessionRouteArg, FromSession } from '@spinajs/rbac-http';
19
19
  import { User } from '@spinajs/rbac';
20
+ import { LogoutHandler } from '../logout.js';
20
21
  /**
21
22
  * Authentication endpoints.
22
23
  * Handles user login, logout, and current-session inspection.
@@ -60,6 +61,12 @@ let LoginController = class LoginController extends BaseController {
60
61
  ];
61
62
  let result;
62
63
  session.Data.set('User', user.Uuid);
64
+ // Default active role = first role from the user's role list.
65
+ // Users with multiple roles can later switch via /auth/active-role.
66
+ const activeRole = user.Role?.[0];
67
+ if (activeRole) {
68
+ session.Data.set('ActiveRole', activeRole);
69
+ }
63
70
  // we have two states for user
64
71
  // LOGGED - when user use proper login/password and session is created
65
72
  // AUTHORIZED - when user is atuhenticated eg. by 2fa check. If 2fa is disabled
@@ -87,12 +94,12 @@ let LoginController = class LoginController extends BaseController {
87
94
  else {
88
95
  session.Data.set('Authorized', true);
89
96
  const grants = this.AC.getGrants();
90
- const userGrants = user.Role.map(r => _unwindGrants(r, grants));
91
- const combinedGrants = Object.assign({}, ...userGrants);
97
+ const combinedGrants = activeRole ? _unwindGrants(activeRole, grants) : {};
92
98
  // dehydrateWithRelations({ dateTimeFormat: 'iso' }) converts DateTime to ISO strings
93
99
  // at runtime — the ORM types don't reflect the dateTimeFormat option in generics
94
100
  result = {
95
101
  ...user.dehydrateWithRelations({ dateTimeFormat: "iso" }),
102
+ ActiveRole: activeRole,
96
103
  Grants: combinedGrants,
97
104
  };
98
105
  }
@@ -117,43 +124,52 @@ let LoginController = class LoginController extends BaseController {
117
124
  /**
118
125
  * Logout
119
126
  * Destroys the current session identified by the `ssid` cookie and clears the cookie on the client.
127
+ * If an impersonation is active, the session is NOT destroyed — instead the
128
+ * impersonation is ended and the original user resumes their session.
120
129
  * Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
121
130
  * @security cookieAuth
122
131
  * @response 401 No active session
123
132
  */
124
- async logout(ssid) {
133
+ async logout(ssid, session, user) {
125
134
  if (!ssid) {
126
135
  return new Ok();
127
136
  }
128
- await this.SessionProvider.delete(ssid);
129
- // send empty cookie to confirm session deletion
130
- return new Ok(null, {
131
- Coockies: [
132
- {
133
- Name: 'ssid',
134
- Value: '',
135
- Options: {
136
- httpOnly: true,
137
- maxAge: 0,
138
- // any optopnal cookie options
139
- // or override default ones
140
- ...this.SessionCookieConfig
141
- },
142
- },
143
- ],
144
- });
137
+ // Delegate to the registered LogoutHandler chain. Each handler decides
138
+ // whether to take ownership of the response (returns non-null) or defer
139
+ // to the next handler. Built-ins:
140
+ // - ImpersonationLogoutHandler (priority 10): reverts an active
141
+ // impersonation and keeps the session alive.
142
+ // - DefaultLogoutHandler (priority 999): destroys the session and clears
143
+ // the ssid cookie.
144
+ // Apps can register additional handlers via @Injectable(LogoutHandler).
145
+ const handlers = await DI.resolve(Array.ofType(LogoutHandler));
146
+ const sorted = [...handlers].sort((a, b) => a.Priority - b.Priority);
147
+ const ctx = { Ssid: ssid, Session: session, User: user };
148
+ for (const handler of sorted) {
149
+ const result = await handler.handle(ctx);
150
+ if (result) {
151
+ return new Ok(result.Body ?? null, { Coockies: result.Cookies ?? [] });
152
+ }
153
+ }
154
+ // No handler claimed the request — should not happen as long as the
155
+ // default handler is registered, but return a clean response anyway.
156
+ return new Ok();
145
157
  }
146
158
  /**
147
159
  * Get current user
148
- * Returns the user object associated with the current session.
160
+ * Returns the user object associated with the current session along with the
161
+ * currently active role and the full list of roles the user may switch to.
149
162
  * Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
150
163
  * @security cookieAuth
151
- * @returns {IUserProfile} User data from the current session
164
+ * @returns {User} User data from the current session
152
165
  * @response 401 No active session
153
166
  */
154
- async whoami(User) {
155
- // user is taken from session data
156
- return new Ok(User);
167
+ async whoami(User, ActiveRole) {
168
+ return new Ok({
169
+ ...User.dehydrateWithRelations({ dateTimeFormat: 'iso' }),
170
+ ActiveRole: ActiveRole ?? User.Role?.[0],
171
+ AvailableRoles: User.Role ?? [],
172
+ });
157
173
  }
158
174
  };
159
175
  __decorate([
@@ -207,16 +223,19 @@ __decorate([
207
223
  Get(),
208
224
  Policy(LoggedPolicy),
209
225
  __param(0, Cookie(true)),
226
+ __param(1, SessionRouteArg()),
227
+ __param(2, UserRouteArg()),
210
228
  __metadata("design:type", Function),
211
- __metadata("design:paramtypes", [String]),
229
+ __metadata("design:paramtypes", [String, Object, User]),
212
230
  __metadata("design:returntype", Promise)
213
231
  ], LoginController.prototype, "logout", null);
214
232
  __decorate([
215
233
  Get(),
216
234
  Policy(LoggedPolicy),
217
235
  __param(0, UserRouteArg()),
236
+ __param(1, FromSession()),
218
237
  __metadata("design:type", Function),
219
- __metadata("design:paramtypes", [User]),
238
+ __metadata("design:paramtypes", [User, String]),
220
239
  __metadata("design:returntype", Promise)
221
240
  ], LoginController.prototype, "whoami", null);
222
241
  LoginController = __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare const ImpersonateDtoSchema: {
2
+ $schema: string;
3
+ title: string;
4
+ type: string;
5
+ properties: {
6
+ TargetUuid: {
7
+ type: string;
8
+ format: string;
9
+ description: string;
10
+ };
11
+ Password: {
12
+ type: string;
13
+ maxLength: number;
14
+ description: string;
15
+ };
16
+ };
17
+ required: string[];
18
+ };
19
+ export declare class ImpersonateDto {
20
+ TargetUuid: string;
21
+ Password?: string;
22
+ constructor(data: any);
23
+ }
24
+ //# sourceMappingURL=impersonate-dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impersonate-dto.d.ts","sourceRoot":"","sources":["../../../src/dto/impersonate-dto.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;CAShC,CAAC;AAEF,qBACa,cAAc;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEb,IAAI,EAAE,GAAG;CAGtB"}
@@ -0,0 +1,31 @@
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 { Schema } from '@spinajs/validation';
11
+ export const ImpersonateDtoSchema = {
12
+ $schema: 'http://json-schema.org/draft-07/schema#',
13
+ title: 'Impersonate DTO',
14
+ type: 'object',
15
+ properties: {
16
+ TargetUuid: { type: 'string', format: 'uuid', description: 'UUID of the user to impersonate' },
17
+ Password: { type: 'string', maxLength: 32, description: 'Impersonator password (required when rbac.impersonation.requirePassword is true)' },
18
+ },
19
+ required: ['TargetUuid'],
20
+ };
21
+ let ImpersonateDto = class ImpersonateDto {
22
+ constructor(data) {
23
+ Object.assign(this, data);
24
+ }
25
+ };
26
+ ImpersonateDto = __decorate([
27
+ Schema(ImpersonateDtoSchema),
28
+ __metadata("design:paramtypes", [Object])
29
+ ], ImpersonateDto);
30
+ export { ImpersonateDto };
31
+ //# sourceMappingURL=impersonate-dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impersonate-dto.js","sourceRoot":"","sources":["../../../src/dto/impersonate-dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,iBAAiB;IACxB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,iCAAiC,EAAE;QAC9F,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,kFAAkF,EAAE;KAC7I;IACD,QAAQ,EAAE,CAAC,YAAY,CAAC;CACzB,CAAC;AAGK,IAAM,cAAc,GAApB,MAAM,cAAc;IAKzB,YAAY,IAAS;QACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF,CAAA;AARY,cAAc;IAD1B,MAAM,CAAC,oBAAoB,CAAC;;GAChB,cAAc,CAQ1B"}
@@ -0,0 +1,24 @@
1
+ export declare const SwitchRoleDtoSchema: {
2
+ $schema: string;
3
+ title: string;
4
+ type: string;
5
+ properties: {
6
+ Role: {
7
+ type: string;
8
+ minLength: number;
9
+ description: string;
10
+ };
11
+ Password: {
12
+ type: string;
13
+ maxLength: number;
14
+ description: string;
15
+ };
16
+ };
17
+ required: string[];
18
+ };
19
+ export declare class SwitchRoleDto {
20
+ Role: string;
21
+ Password?: string;
22
+ constructor(data: any);
23
+ }
24
+ //# sourceMappingURL=switchRole-dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switchRole-dto.d.ts","sourceRoot":"","sources":["../../../src/dto/switchRole-dto.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;CAS/B,CAAC;AAEF,qBACa,aAAa;IACjB,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEb,IAAI,EAAE,GAAG;CAGtB"}
@@ -0,0 +1,31 @@
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 { Schema } from '@spinajs/validation';
11
+ export const SwitchRoleDtoSchema = {
12
+ $schema: 'http://json-schema.org/draft-07/schema#',
13
+ title: 'Switch active role DTO',
14
+ type: 'object',
15
+ properties: {
16
+ Role: { type: 'string', minLength: 1, description: 'Role to activate. Must be one of the user\'s assigned roles.' },
17
+ Password: { type: 'string', maxLength: 32, description: 'User password. Required when activating roles listed in rbac.roleSwitch.requirePassword.' },
18
+ },
19
+ required: ['Role'],
20
+ };
21
+ let SwitchRoleDto = class SwitchRoleDto {
22
+ constructor(data) {
23
+ Object.assign(this, data);
24
+ }
25
+ };
26
+ SwitchRoleDto = __decorate([
27
+ Schema(SwitchRoleDtoSchema),
28
+ __metadata("design:paramtypes", [Object])
29
+ ], SwitchRoleDto);
30
+ export { SwitchRoleDto };
31
+ //# sourceMappingURL=switchRole-dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switchRole-dto.js","sourceRoot":"","sources":["../../../src/dto/switchRole-dto.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,OAAO,EAAE,yCAAyC;IAClD,KAAK,EAAE,wBAAwB;IAC/B,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,8DAA8D,EAAE;QACnH,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,0FAA0F,EAAE;KACrJ;IACD,QAAQ,EAAE,CAAC,MAAM,CAAC;CACnB,CAAC;AAGK,IAAM,aAAa,GAAnB,MAAM,aAAa;IAKxB,YAAY,IAAS;QACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF,CAAA;AARY,aAAa;IADzB,MAAM,CAAC,mBAAmB,CAAC;;GACf,aAAa,CAQzB"}
@@ -0,0 +1,14 @@
1
+ import { SessionProvider } from '@spinajs/rbac';
2
+ import { LogoutHandler, ILogoutContext, ILogoutResult } from '../logout.js';
3
+ /**
4
+ * Default logout handler: deletes the session and clears the ssid cookie.
5
+ * Runs last (priority 999) so any earlier handler can short-circuit (e.g.
6
+ * the impersonation revert handler) before the session is destroyed.
7
+ */
8
+ export declare class DefaultLogoutHandler extends LogoutHandler {
9
+ Priority: number;
10
+ protected SessionProvider: SessionProvider;
11
+ protected SessionCookieConfig: Record<string, unknown>;
12
+ handle(context: ILogoutContext): Promise<ILogoutResult | null>;
13
+ }
14
+ //# sourceMappingURL=DefaultLogoutHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultLogoutHandler.d.ts","sourceRoot":"","sources":["../../../src/handlers/DefaultLogoutHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5E;;;;GAIG;AACH,qBACa,oBAAqB,SAAQ,aAAa;IAC9C,QAAQ,SAAO;IAGtB,SAAS,CAAC,eAAe,EAAG,eAAe,CAAC;IAG5C,SAAS,CAAC,mBAAmB,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3C,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;CAuB5E"}
@@ -0,0 +1,58 @@
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 { Injectable } from '@spinajs/di';
11
+ import { AutoinjectService, Config } from '@spinajs/configuration';
12
+ import { SessionProvider } from '@spinajs/rbac';
13
+ import { LogoutHandler } from '../logout.js';
14
+ /**
15
+ * Default logout handler: deletes the session and clears the ssid cookie.
16
+ * Runs last (priority 999) so any earlier handler can short-circuit (e.g.
17
+ * the impersonation revert handler) before the session is destroyed.
18
+ */
19
+ let DefaultLogoutHandler = class DefaultLogoutHandler extends LogoutHandler {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.Priority = 999;
23
+ }
24
+ async handle(context) {
25
+ if (!context.Ssid) {
26
+ // Nothing to delete; still return a result so the chain stops.
27
+ return { Body: null };
28
+ }
29
+ await this.SessionProvider.delete(context.Ssid);
30
+ return {
31
+ Body: null,
32
+ Cookies: [
33
+ {
34
+ Name: 'ssid',
35
+ Value: '',
36
+ Options: {
37
+ httpOnly: true,
38
+ maxAge: 0,
39
+ ...this.SessionCookieConfig,
40
+ },
41
+ },
42
+ ],
43
+ };
44
+ }
45
+ };
46
+ __decorate([
47
+ AutoinjectService('rbac.session'),
48
+ __metadata("design:type", SessionProvider)
49
+ ], DefaultLogoutHandler.prototype, "SessionProvider", void 0);
50
+ __decorate([
51
+ Config('rbac.session.cookie', {}),
52
+ __metadata("design:type", Object)
53
+ ], DefaultLogoutHandler.prototype, "SessionCookieConfig", void 0);
54
+ DefaultLogoutHandler = __decorate([
55
+ Injectable(LogoutHandler)
56
+ ], DefaultLogoutHandler);
57
+ export { DefaultLogoutHandler };
58
+ //# sourceMappingURL=DefaultLogoutHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultLogoutHandler.js","sourceRoot":"","sources":["../../../src/handlers/DefaultLogoutHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAiC,MAAM,cAAc,CAAC;AAE5E;;;;GAIG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,aAAa;IAAhD;;QACE,aAAQ,GAAG,GAAG,CAAC;IA+BxB,CAAC;IAvBQ,KAAK,CAAC,MAAM,CAAC,OAAuB;QACzC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,+DAA+D;YAC/D,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACxB,CAAC;QAED,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEhD,OAAO;YACL,IAAI,EAAE,IAAI;YACV,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,EAAE;oBACT,OAAO,EAAE;wBACP,QAAQ,EAAE,IAAI;wBACd,MAAM,EAAE,CAAC;wBACT,GAAG,IAAI,CAAC,mBAAmB;qBAC5B;iBACF;aACF;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA5BW;IADT,iBAAiB,CAAC,cAAc,CAAC;8BACN,eAAe;6DAAC;AAGlC;IADT,MAAM,CAAC,qBAAqB,EAAE,EAAE,CAAC;;iEACsB;AAP7C,oBAAoB;IADhC,UAAU,CAAC,aAAa,CAAC;GACb,oBAAoB,CAgChC"}
@@ -0,0 +1,18 @@
1
+ import { SessionProvider, User } from '@spinajs/rbac';
2
+ import { LogoutHandler, ILogoutContext, ILogoutResult } from '../logout.js';
3
+ /**
4
+ * Logout handler that detects an active impersonation and reverts it instead
5
+ * of destroying the session. Runs early (priority 10) so it short-circuits
6
+ * the default session-deletion handler when applicable.
7
+ */
8
+ export declare class ImpersonationLogoutHandler extends LogoutHandler {
9
+ Priority: number;
10
+ protected SessionProvider: SessionProvider;
11
+ handle(context: ILogoutContext): Promise<ILogoutResult | null>;
12
+ /**
13
+ * Hook for tests to intercept event emission without stubbing the module-level
14
+ * `_ev` ESM binding.
15
+ */
16
+ protected emitEvent(original: User, target: User): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=ImpersonationLogoutHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImpersonationLogoutHandler.d.ts","sourceRoot":"","sources":["../../../src/handlers/ImpersonationLogoutHandler.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,IAAI,EAA0B,MAAM,eAAe,CAAC;AAE9E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5E;;;;GAIG;AACH,qBACa,0BAA2B,SAAQ,aAAa;IACpD,QAAQ,SAAM;IAGrB,SAAS,CAAC,eAAe,EAAG,eAAe,CAAC;IAE/B,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA0B3E;;;OAGG;IACH,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAGjE"}
@@ -0,0 +1,63 @@
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 { Injectable } from '@spinajs/di';
11
+ import { AutoinjectService } from '@spinajs/configuration';
12
+ import { SessionProvider, User, UserImpersonationEnded } from '@spinajs/rbac';
13
+ import { _ev } from '@spinajs/queue';
14
+ import { LogoutHandler } from '../logout.js';
15
+ /**
16
+ * Logout handler that detects an active impersonation and reverts it instead
17
+ * of destroying the session. Runs early (priority 10) so it short-circuits
18
+ * the default session-deletion handler when applicable.
19
+ */
20
+ let ImpersonationLogoutHandler = class ImpersonationLogoutHandler extends LogoutHandler {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.Priority = 10;
24
+ }
25
+ async handle(context) {
26
+ const session = context.Session;
27
+ if (!session)
28
+ return null;
29
+ const impersonatorUuid = session.Data.get('Impersonator');
30
+ if (!impersonatorUuid)
31
+ return null;
32
+ const original = await User.getByUuid(impersonatorUuid);
33
+ session.Data.set('User', original.Uuid);
34
+ session.Data.delete('Impersonator');
35
+ session.Data.delete('ImpersonationStartedAt');
36
+ const restoredActiveRole = session.Data.get('OriginalActiveRole') ?? original.Role?.[0];
37
+ if (restoredActiveRole) {
38
+ session.Data.set('ActiveRole', restoredActiveRole);
39
+ }
40
+ session.Data.delete('OriginalActiveRole');
41
+ await this.SessionProvider.save(session);
42
+ await this.emitEvent(original, context.User);
43
+ // Take ownership of the response: no cookie change — the original user's
44
+ // session continues.
45
+ return { Body: { ImpersonationEnded: true } };
46
+ }
47
+ /**
48
+ * Hook for tests to intercept event emission without stubbing the module-level
49
+ * `_ev` ESM binding.
50
+ */
51
+ emitEvent(original, target) {
52
+ return _ev(new UserImpersonationEnded(original, target))();
53
+ }
54
+ };
55
+ __decorate([
56
+ AutoinjectService('rbac.session'),
57
+ __metadata("design:type", SessionProvider)
58
+ ], ImpersonationLogoutHandler.prototype, "SessionProvider", void 0);
59
+ ImpersonationLogoutHandler = __decorate([
60
+ Injectable(LogoutHandler)
61
+ ], ImpersonationLogoutHandler);
62
+ export { ImpersonationLogoutHandler };
63
+ //# sourceMappingURL=ImpersonationLogoutHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImpersonationLogoutHandler.js","sourceRoot":"","sources":["../../../src/handlers/ImpersonationLogoutHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,aAAa,EAAiC,MAAM,cAAc,CAAC;AAE5E;;;;GAIG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,aAAa;IAAtD;;QACE,aAAQ,GAAG,EAAE,CAAC;IAsCvB,CAAC;IAjCQ,KAAK,CAAC,MAAM,CAAC,OAAuB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,CAAuB,CAAC;QAChF,IAAI,CAAC,gBAAgB;YAAE,OAAO,IAAI,CAAC;QAEnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QAExD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;QAC9C,MAAM,kBAAkB,GAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAwB,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChH,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAE1C,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAE7C,yEAAyE;QACzE,qBAAqB;QACrB,OAAO,EAAE,IAAI,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,EAAE,CAAC;IAChD,CAAC;IAED;;;OAGG;IACO,SAAS,CAAC,QAAc,EAAE,MAAY;QAC9C,OAAO,GAAG,CAAC,IAAI,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IAC7D,CAAC;CACF,CAAA;AAnCW;IADT,iBAAiB,CAAC,cAAc,CAAC;8BACN,eAAe;mEAAC;AAJjC,0BAA0B;IADtC,UAAU,CAAC,aAAa,CAAC;GACb,0BAA0B,CAuCtC"}
@@ -1,6 +1,11 @@
1
1
  import { Bootstrapper } from '@spinajs/di';
2
2
  export * from './controllers/LoginController.js';
3
+ export * from './controllers/ActiveRoleController.js';
4
+ export * from './controllers/ImpersonationController.js';
3
5
  export * from './controllers/UserController.js';
6
+ export * from './logout.js';
7
+ export * from './handlers/ImpersonationLogoutHandler.js';
8
+ export * from './handlers/DefaultLogoutHandler.js';
4
9
  export * from './controllers/UserMetadataController.js';
5
10
  export * from "./controllers/TwoFactorAuthController.js";
6
11
  export * from "./cli/EnableUser2Fa.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAIvD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,kBAAkB,CAAC;AAGjC,qBACa,wBAAyB,SAAQ,YAAY;IAC/C,SAAS,IAAI,IAAI;CAO3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAIvD,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,iCAAiC,CAAC;AAEhD,cAAc,aAAa,CAAC;AAC5B,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,kBAAkB,CAAC;AAGjC,qBACa,wBAAyB,SAAQ,YAAY;IAC/C,SAAS,IAAI,IAAI;CAO3B"}
package/lib/mjs/index.js CHANGED
@@ -8,7 +8,12 @@ import { Bootstrapper, Injectable } from '@spinajs/di';
8
8
  import { UserMetadataBase } from '@spinajs/rbac';
9
9
  import { TWO_FA_METATADATA_KEYS } from './2fa/Default2FaToken.js';
10
10
  export * from './controllers/LoginController.js';
11
+ export * from './controllers/ActiveRoleController.js';
12
+ export * from './controllers/ImpersonationController.js';
11
13
  export * from './controllers/UserController.js';
14
+ export * from './logout.js';
15
+ export * from './handlers/ImpersonationLogoutHandler.js';
16
+ export * from './handlers/DefaultLogoutHandler.js';
12
17
  export * from './controllers/UserMetadataController.js';
13
18
  export * from "./controllers/TwoFactorAuthController.js";
14
19
  export * from "./cli/EnableUser2Fa.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,kBAAkB,CAAC;AAI1B,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,YAAY;IAC/C,SAAS;QACZ,gBAAgB,CAAC,WAAW,GAAG;YAC3B,GAAG,gBAAgB,CAAC,WAAW;YAC/B,sBAAsB,CAAC,KAAK;YAC5B,sBAAsB,CAAC,GAAG;SAC7B,CAAA;IACL,CAAC;CACJ,CAAA;AARY,wBAAwB;IADpC,UAAU,CAAC,YAAY,CAAC;GACZ,wBAAwB,CAQpC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,cAAc,kCAAkC,CAAC;AACjD,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,iCAAiC,CAAC;AAEhD,cAAc,aAAa,CAAC;AAC5B,cAAc,0CAA0C,CAAC;AACzD,cAAc,oCAAoC,CAAC;AACnD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AAEzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,kBAAkB,CAAC;AAI1B,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,YAAY;IAC/C,SAAS;QACZ,gBAAgB,CAAC,WAAW,GAAG;YAC3B,GAAG,gBAAgB,CAAC,WAAW;YAC/B,sBAAsB,CAAC,KAAK;YAC5B,sBAAsB,CAAC,GAAG;SAC7B,CAAA;IACL,CAAC;CACJ,CAAA;AARY,wBAAwB;IADpC,UAAU,CAAC,YAAY,CAAC;GACZ,wBAAwB,CAQpC"}
@@ -0,0 +1,51 @@
1
+ import type { ISession, User } from '@spinajs/rbac';
2
+ /**
3
+ * Per-request context handed to each {@link LogoutHandler} during logout.
4
+ * The session may be null when the caller has no active session — handlers
5
+ * should treat that as a no-op.
6
+ */
7
+ export interface ILogoutContext {
8
+ /** Raw signed session cookie value (already unsigned by the framework) */
9
+ Ssid: string;
10
+ /** Restored session, or null when none is active */
11
+ Session: ISession | null;
12
+ /** Logged-in user as resolved by RbacMiddleware */
13
+ User: User;
14
+ }
15
+ /** Cookie operation a handler may attach to its response */
16
+ export interface ILogoutCookie {
17
+ Name: string;
18
+ Value: string;
19
+ Options: Record<string, unknown>;
20
+ }
21
+ /** Response payload a handler returns when it takes ownership of the logout */
22
+ export interface ILogoutResult {
23
+ /** Response body */
24
+ Body?: unknown;
25
+ /** Cookie operations to attach */
26
+ Cookies?: ILogoutCookie[];
27
+ }
28
+ /**
29
+ * Pluggable logout step. Handlers are resolved via `DI.resolve(Array.ofType(LogoutHandler))`
30
+ * by the logout controller and executed in ascending Priority order. The first
31
+ * handler that returns a non-null result takes ownership of the response — the
32
+ * chain stops there. Returning null defers to the next handler.
33
+ *
34
+ * Built-ins:
35
+ * - {@link ImpersonationLogoutHandler} (priority 10) — when an impersonation
36
+ * is active, revert it and keep the session alive.
37
+ * - {@link DefaultLogoutHandler} (priority 999) — destroy the session and
38
+ * clear the ssid cookie.
39
+ *
40
+ * Register custom handlers with @Injectable(LogoutHandler). Choose a Priority
41
+ * lower than 999 to run before the default session destruction.
42
+ */
43
+ export declare abstract class LogoutHandler {
44
+ /**
45
+ * Lower runs first. Default 100. The default cleanup handler runs at 999;
46
+ * pick a value below that to run before it.
47
+ */
48
+ Priority: number;
49
+ abstract handle(context: ILogoutContext): Promise<ILogoutResult | null>;
50
+ }
51
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IAEb,oDAAoD;IACpD,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEzB,mDAAmD;IACnD,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,oBAAoB;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,kCAAkC;IAClC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,8BAAsB,aAAa;IACjC;;;OAGG;IACI,QAAQ,EAAE,MAAM,CAAO;aAEd,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;CAC/E"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Pluggable logout step. Handlers are resolved via `DI.resolve(Array.ofType(LogoutHandler))`
3
+ * by the logout controller and executed in ascending Priority order. The first
4
+ * handler that returns a non-null result takes ownership of the response — the
5
+ * chain stops there. Returning null defers to the next handler.
6
+ *
7
+ * Built-ins:
8
+ * - {@link ImpersonationLogoutHandler} (priority 10) — when an impersonation
9
+ * is active, revert it and keep the session alive.
10
+ * - {@link DefaultLogoutHandler} (priority 999) — destroy the session and
11
+ * clear the ssid cookie.
12
+ *
13
+ * Register custom handlers with @Injectable(LogoutHandler). Choose a Priority
14
+ * lower than 999 to run before the default session destruction.
15
+ */
16
+ export class LogoutHandler {
17
+ constructor() {
18
+ /**
19
+ * Lower runs first. Default 100. The default cleanup handler runs at 999;
20
+ * pick a value below that to run before it.
21
+ */
22
+ this.Priority = 100;
23
+ }
24
+ }
25
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/logout.ts"],"names":[],"mappings":"AAkCA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAgB,aAAa;IAAnC;QACE;;;WAGG;QACI,aAAQ,GAAW,GAAG,CAAC;IAGhC,CAAC;CAAA"}