@spinajs/rbac-http-token 2.0.507

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 (198) hide show
  1. package/README.md +152 -0
  2. package/lib/cjs/actions.d.ts +119 -0
  3. package/lib/cjs/actions.d.ts.map +1 -0
  4. package/lib/cjs/actions.js +257 -0
  5. package/lib/cjs/actions.js.map +1 -0
  6. package/lib/cjs/cli/CreateToken.d.ts +13 -0
  7. package/lib/cjs/cli/CreateToken.d.ts.map +1 -0
  8. package/lib/cjs/cli/CreateToken.js +56 -0
  9. package/lib/cjs/cli/CreateToken.js.map +1 -0
  10. package/lib/cjs/cli/DeleteExpiredTokens.d.ts +11 -0
  11. package/lib/cjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
  12. package/lib/cjs/cli/DeleteExpiredTokens.js +39 -0
  13. package/lib/cjs/cli/DeleteExpiredTokens.js.map +1 -0
  14. package/lib/cjs/cli/DeleteToken.d.ts +7 -0
  15. package/lib/cjs/cli/DeleteToken.d.ts.map +1 -0
  16. package/lib/cjs/cli/DeleteToken.js +36 -0
  17. package/lib/cjs/cli/DeleteToken.js.map +1 -0
  18. package/lib/cjs/cli/GrantTokenRole.d.ts +7 -0
  19. package/lib/cjs/cli/GrantTokenRole.d.ts.map +1 -0
  20. package/lib/cjs/cli/GrantTokenRole.js +37 -0
  21. package/lib/cjs/cli/GrantTokenRole.js.map +1 -0
  22. package/lib/cjs/cli/RevokeTokenRole.d.ts +12 -0
  23. package/lib/cjs/cli/RevokeTokenRole.d.ts.map +1 -0
  24. package/lib/cjs/cli/RevokeTokenRole.js +42 -0
  25. package/lib/cjs/cli/RevokeTokenRole.js.map +1 -0
  26. package/lib/cjs/config/rbac-http-token.d.ts +71 -0
  27. package/lib/cjs/config/rbac-http-token.d.ts.map +1 -0
  28. package/lib/cjs/config/rbac-http-token.js +98 -0
  29. package/lib/cjs/config/rbac-http-token.js.map +1 -0
  30. package/lib/cjs/controllers/AccessTokenController.d.ts +139 -0
  31. package/lib/cjs/controllers/AccessTokenController.d.ts.map +1 -0
  32. package/lib/cjs/controllers/AccessTokenController.js +264 -0
  33. package/lib/cjs/controllers/AccessTokenController.js.map +1 -0
  34. package/lib/cjs/dto/create-token-dto.d.ts +34 -0
  35. package/lib/cjs/dto/create-token-dto.d.ts.map +1 -0
  36. package/lib/cjs/dto/create-token-dto.js +35 -0
  37. package/lib/cjs/dto/create-token-dto.js.map +1 -0
  38. package/lib/cjs/events/AccessTokenCreated.d.ts +4 -0
  39. package/lib/cjs/events/AccessTokenCreated.d.ts.map +1 -0
  40. package/lib/cjs/events/AccessTokenCreated.js +18 -0
  41. package/lib/cjs/events/AccessTokenCreated.js.map +1 -0
  42. package/lib/cjs/events/AccessTokenDeleted.d.ts +4 -0
  43. package/lib/cjs/events/AccessTokenDeleted.d.ts.map +1 -0
  44. package/lib/cjs/events/AccessTokenDeleted.js +18 -0
  45. package/lib/cjs/events/AccessTokenDeleted.js.map +1 -0
  46. package/lib/cjs/events/AccessTokenEvent.d.ts +10 -0
  47. package/lib/cjs/events/AccessTokenEvent.d.ts.map +1 -0
  48. package/lib/cjs/events/AccessTokenEvent.js +26 -0
  49. package/lib/cjs/events/AccessTokenEvent.js.map +1 -0
  50. package/lib/cjs/events/AccessTokenRoleGranted.d.ts +7 -0
  51. package/lib/cjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
  52. package/lib/cjs/events/AccessTokenRoleGranted.js +27 -0
  53. package/lib/cjs/events/AccessTokenRoleGranted.js.map +1 -0
  54. package/lib/cjs/events/AccessTokenRoleRevoked.d.ts +7 -0
  55. package/lib/cjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
  56. package/lib/cjs/events/AccessTokenRoleRevoked.js +27 -0
  57. package/lib/cjs/events/AccessTokenRoleRevoked.js.map +1 -0
  58. package/lib/cjs/events/index.d.ts +6 -0
  59. package/lib/cjs/events/index.d.ts.map +1 -0
  60. package/lib/cjs/events/index.js +22 -0
  61. package/lib/cjs/events/index.js.map +1 -0
  62. package/lib/cjs/generator.d.ts +12 -0
  63. package/lib/cjs/generator.d.ts.map +1 -0
  64. package/lib/cjs/generator.js +42 -0
  65. package/lib/cjs/generator.js.map +1 -0
  66. package/lib/cjs/index.d.ts +20 -0
  67. package/lib/cjs/index.d.ts.map +1 -0
  68. package/lib/cjs/index.js +39 -0
  69. package/lib/cjs/index.js.map +1 -0
  70. package/lib/cjs/interfaces.d.ts +57 -0
  71. package/lib/cjs/interfaces.d.ts.map +1 -0
  72. package/lib/cjs/interfaces.js +11 -0
  73. package/lib/cjs/interfaces.js.map +1 -0
  74. package/lib/cjs/middlewares.d.ts +76 -0
  75. package/lib/cjs/middlewares.d.ts.map +1 -0
  76. package/lib/cjs/middlewares.js +181 -0
  77. package/lib/cjs/middlewares.js.map +1 -0
  78. package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
  79. package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
  80. package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +38 -0
  81. package/lib/cjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
  82. package/lib/cjs/models/AccessToken.d.ts +55 -0
  83. package/lib/cjs/models/AccessToken.d.ts.map +1 -0
  84. package/lib/cjs/models/AccessToken.js +73 -0
  85. package/lib/cjs/models/AccessToken.js.map +1 -0
  86. package/lib/cjs/package.json +1 -0
  87. package/lib/cjs/policies/NoImpersonationPolicy.d.ts +28 -0
  88. package/lib/cjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
  89. package/lib/cjs/policies/NoImpersonationPolicy.js +45 -0
  90. package/lib/cjs/policies/NoImpersonationPolicy.js.map +1 -0
  91. package/lib/cjs/policies/NoTokenAuthPolicy.d.ts +12 -0
  92. package/lib/cjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
  93. package/lib/cjs/policies/NoTokenAuthPolicy.js +24 -0
  94. package/lib/cjs/policies/NoTokenAuthPolicy.js.map +1 -0
  95. package/lib/cjs/policies/TokenPolicy.d.ts +49 -0
  96. package/lib/cjs/policies/TokenPolicy.d.ts.map +1 -0
  97. package/lib/cjs/policies/TokenPolicy.js +79 -0
  98. package/lib/cjs/policies/TokenPolicy.js.map +1 -0
  99. package/lib/mjs/actions.d.ts +119 -0
  100. package/lib/mjs/actions.d.ts.map +1 -0
  101. package/lib/mjs/actions.js +242 -0
  102. package/lib/mjs/actions.js.map +1 -0
  103. package/lib/mjs/cli/CreateToken.d.ts +13 -0
  104. package/lib/mjs/cli/CreateToken.d.ts.map +1 -0
  105. package/lib/mjs/cli/CreateToken.js +53 -0
  106. package/lib/mjs/cli/CreateToken.js.map +1 -0
  107. package/lib/mjs/cli/DeleteExpiredTokens.d.ts +11 -0
  108. package/lib/mjs/cli/DeleteExpiredTokens.d.ts.map +1 -0
  109. package/lib/mjs/cli/DeleteExpiredTokens.js +36 -0
  110. package/lib/mjs/cli/DeleteExpiredTokens.js.map +1 -0
  111. package/lib/mjs/cli/DeleteToken.d.ts +7 -0
  112. package/lib/mjs/cli/DeleteToken.d.ts.map +1 -0
  113. package/lib/mjs/cli/DeleteToken.js +33 -0
  114. package/lib/mjs/cli/DeleteToken.js.map +1 -0
  115. package/lib/mjs/cli/GrantTokenRole.d.ts +7 -0
  116. package/lib/mjs/cli/GrantTokenRole.d.ts.map +1 -0
  117. package/lib/mjs/cli/GrantTokenRole.js +34 -0
  118. package/lib/mjs/cli/GrantTokenRole.js.map +1 -0
  119. package/lib/mjs/cli/RevokeTokenRole.d.ts +12 -0
  120. package/lib/mjs/cli/RevokeTokenRole.d.ts.map +1 -0
  121. package/lib/mjs/cli/RevokeTokenRole.js +39 -0
  122. package/lib/mjs/cli/RevokeTokenRole.js.map +1 -0
  123. package/lib/mjs/config/rbac-http-token.d.ts +71 -0
  124. package/lib/mjs/config/rbac-http-token.d.ts.map +1 -0
  125. package/lib/mjs/config/rbac-http-token.js +96 -0
  126. package/lib/mjs/config/rbac-http-token.js.map +1 -0
  127. package/lib/mjs/controllers/AccessTokenController.d.ts +139 -0
  128. package/lib/mjs/controllers/AccessTokenController.d.ts.map +1 -0
  129. package/lib/mjs/controllers/AccessTokenController.js +261 -0
  130. package/lib/mjs/controllers/AccessTokenController.js.map +1 -0
  131. package/lib/mjs/dto/create-token-dto.d.ts +34 -0
  132. package/lib/mjs/dto/create-token-dto.d.ts.map +1 -0
  133. package/lib/mjs/dto/create-token-dto.js +32 -0
  134. package/lib/mjs/dto/create-token-dto.js.map +1 -0
  135. package/lib/mjs/events/AccessTokenCreated.d.ts +4 -0
  136. package/lib/mjs/events/AccessTokenCreated.d.ts.map +1 -0
  137. package/lib/mjs/events/AccessTokenCreated.js +15 -0
  138. package/lib/mjs/events/AccessTokenCreated.js.map +1 -0
  139. package/lib/mjs/events/AccessTokenDeleted.d.ts +4 -0
  140. package/lib/mjs/events/AccessTokenDeleted.d.ts.map +1 -0
  141. package/lib/mjs/events/AccessTokenDeleted.js +15 -0
  142. package/lib/mjs/events/AccessTokenDeleted.js.map +1 -0
  143. package/lib/mjs/events/AccessTokenEvent.d.ts +10 -0
  144. package/lib/mjs/events/AccessTokenEvent.d.ts.map +1 -0
  145. package/lib/mjs/events/AccessTokenEvent.js +23 -0
  146. package/lib/mjs/events/AccessTokenEvent.js.map +1 -0
  147. package/lib/mjs/events/AccessTokenRoleGranted.d.ts +7 -0
  148. package/lib/mjs/events/AccessTokenRoleGranted.d.ts.map +1 -0
  149. package/lib/mjs/events/AccessTokenRoleGranted.js +24 -0
  150. package/lib/mjs/events/AccessTokenRoleGranted.js.map +1 -0
  151. package/lib/mjs/events/AccessTokenRoleRevoked.d.ts +7 -0
  152. package/lib/mjs/events/AccessTokenRoleRevoked.d.ts.map +1 -0
  153. package/lib/mjs/events/AccessTokenRoleRevoked.js +24 -0
  154. package/lib/mjs/events/AccessTokenRoleRevoked.js.map +1 -0
  155. package/lib/mjs/events/index.d.ts +6 -0
  156. package/lib/mjs/events/index.d.ts.map +1 -0
  157. package/lib/mjs/events/index.js +6 -0
  158. package/lib/mjs/events/index.js.map +1 -0
  159. package/lib/mjs/generator.d.ts +12 -0
  160. package/lib/mjs/generator.d.ts.map +1 -0
  161. package/lib/mjs/generator.js +39 -0
  162. package/lib/mjs/generator.js.map +1 -0
  163. package/lib/mjs/index.d.ts +20 -0
  164. package/lib/mjs/index.d.ts.map +1 -0
  165. package/lib/mjs/index.js +23 -0
  166. package/lib/mjs/index.js.map +1 -0
  167. package/lib/mjs/interfaces.d.ts +57 -0
  168. package/lib/mjs/interfaces.d.ts.map +1 -0
  169. package/lib/mjs/interfaces.js +7 -0
  170. package/lib/mjs/interfaces.js.map +1 -0
  171. package/lib/mjs/middlewares.d.ts +76 -0
  172. package/lib/mjs/middlewares.d.ts.map +1 -0
  173. package/lib/mjs/middlewares.js +178 -0
  174. package/lib/mjs/middlewares.js.map +1 -0
  175. package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts +6 -0
  176. package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map +1 -0
  177. package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js +35 -0
  178. package/lib/mjs/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js.map +1 -0
  179. package/lib/mjs/models/AccessToken.d.ts +55 -0
  180. package/lib/mjs/models/AccessToken.d.ts.map +1 -0
  181. package/lib/mjs/models/AccessToken.js +70 -0
  182. package/lib/mjs/models/AccessToken.js.map +1 -0
  183. package/lib/mjs/package.json +1 -0
  184. package/lib/mjs/policies/NoImpersonationPolicy.d.ts +28 -0
  185. package/lib/mjs/policies/NoImpersonationPolicy.d.ts.map +1 -0
  186. package/lib/mjs/policies/NoImpersonationPolicy.js +41 -0
  187. package/lib/mjs/policies/NoImpersonationPolicy.js.map +1 -0
  188. package/lib/mjs/policies/NoTokenAuthPolicy.d.ts +12 -0
  189. package/lib/mjs/policies/NoTokenAuthPolicy.d.ts.map +1 -0
  190. package/lib/mjs/policies/NoTokenAuthPolicy.js +20 -0
  191. package/lib/mjs/policies/NoTokenAuthPolicy.js.map +1 -0
  192. package/lib/mjs/policies/TokenPolicy.d.ts +49 -0
  193. package/lib/mjs/policies/TokenPolicy.d.ts.map +1 -0
  194. package/lib/mjs/policies/TokenPolicy.js +75 -0
  195. package/lib/mjs/policies/TokenPolicy.js.map +1 -0
  196. package/lib/tsconfig.cjs.tsbuildinfo +1 -0
  197. package/lib/tsconfig.mjs.tsbuildinfo +1 -0
  198. package/package.json +78 -0
@@ -0,0 +1,35 @@
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
+ /* eslint-disable @typescript-eslint/no-unused-vars */
8
+ import { OrmMigration, Migration } from '@spinajs/orm';
9
+ let RbacHttpTokenInitial_2026_08_11_01_00_00 = class RbacHttpTokenInitial_2026_08_11_01_00_00 extends OrmMigration {
10
+ async up(connection) {
11
+ await connection.schema().createTable('rbac_access_tokens', (table) => {
12
+ table.int('Id').primaryKey().autoIncrement();
13
+ table.string('Uuid', 36).notNull();
14
+ table.string('Name', 128).notNull();
15
+ table.string('Token', 64).notNull();
16
+ table.string('Roles', 512).notNull();
17
+ table.dateTime('ExpiresAt');
18
+ table.dateTime('CreatedAt').notNull().default().dateTime();
19
+ table.dateTime('LastUsedAt');
20
+ table.int('user_id').notNull();
21
+ table.foreignKey('user_id').references('users', 'Id').cascade();
22
+ });
23
+ await connection.index().unique().table('rbac_access_tokens').name('access_token_hash_idx').columns(['Token']);
24
+ await connection.index().unique().table('rbac_access_tokens').name('access_token_uuid_idx').columns(['Uuid']);
25
+ await connection.index().table('rbac_access_tokens').name('access_token_user_idx').columns(['user_id']);
26
+ await connection.index().table('rbac_access_tokens').name('access_token_expires_idx').columns(['ExpiresAt']);
27
+ }
28
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
29
+ async down(_connection) { }
30
+ };
31
+ RbacHttpTokenInitial_2026_08_11_01_00_00 = __decorate([
32
+ Migration('default')
33
+ ], RbacHttpTokenInitial_2026_08_11_01_00_00);
34
+ export { RbacHttpTokenInitial_2026_08_11_01_00_00 };
35
+ //# sourceMappingURL=RbacHttpTokenInitial_2026_08_11_01_00_00.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RbacHttpTokenInitial_2026_08_11_01_00_00.js","sourceRoot":"","sources":["../../../src/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAsD;AACtD,OAAO,EAAE,YAAY,EAAa,SAAS,EAAE,MAAM,cAAc,CAAC;AAG3D,IAAM,wCAAwC,GAA9C,MAAM,wCAAyC,SAAQ,YAAY;IACjE,KAAK,CAAC,EAAE,CAAC,UAAqB;QACnC,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;YACpE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;YAC7C,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACpC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACpC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACrC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;YAC5B,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC3D,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC7B,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YAC/B,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/G,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9G,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACxG,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/G,CAAC;IAED,gEAAgE;IACzD,KAAK,CAAC,IAAI,CAAC,WAAsB,IAAkB,CAAC;CAC5D,CAAA;AAvBY,wCAAwC;IADpD,SAAS,CAAC,SAAS,CAAC;GACR,wCAAwC,CAuBpD"}
@@ -0,0 +1,55 @@
1
+ import { ModelBase, SingleRelation } from '@spinajs/orm';
2
+ import { User } from '@spinajs/rbac';
3
+ import { DateTime } from 'luxon';
4
+ /**
5
+ * Personal access token. Only the SHA-256 hash of the token is stored;
6
+ * the plaintext is returned once at creation and cannot be recovered.
7
+ */
8
+ export declare class AccessToken extends ModelBase<AccessToken> {
9
+ constructor(data?: Partial<AccessToken>);
10
+ /**
11
+ * Internal row id, never leaves the process. Tokens are addressed by Uuid.
12
+ */
13
+ Id: number;
14
+ /**
15
+ * Public identifier used by the API and CLI.
16
+ */
17
+ Uuid: string;
18
+ /**
19
+ * Human readable label ("ci deploy key").
20
+ */
21
+ Name: string;
22
+ /**
23
+ * SHA-256 hex digest of the plaintext token. Hidden: even the hash is
24
+ * internal - leaking it invites offline correlation.
25
+ */
26
+ Token: string;
27
+ /**
28
+ * Roles allowed on this token. Effective roles at request time are the
29
+ * intersection of this list with the owner's current roles.
30
+ */
31
+ Roles: string[];
32
+ /**
33
+ * Absolute expiration. Null/absent = never expires.
34
+ *
35
+ * NOTE: declared optional rather than as a `DateTime | null` union - the
36
+ * `@DateTime()` decorator reads `design:type`, and a union is emitted as
37
+ * `Object`, which it rejects at decoration time. An optional property still
38
+ * emits `design:type = DateTime` while keeping the absence in the type.
39
+ */
40
+ ExpiresAt?: DateTime;
41
+ CreatedAt: DateTime;
42
+ /**
43
+ * Last successful authentication with this token. Updated throttled.
44
+ * Null/absent until the token is used for the first time - see the note on
45
+ * `ExpiresAt` for why this is optional rather than a nullable union.
46
+ */
47
+ LastUsedAt?: DateTime;
48
+ User: SingleRelation<User>;
49
+ user_id: number;
50
+ /**
51
+ * True when the token carries an expiration in the past.
52
+ */
53
+ get IsExpired(): boolean;
54
+ }
55
+ //# sourceMappingURL=AccessToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessToken.d.ts","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,SAAS,EAAgB,cAAc,EAAE,MAAM,cAAc,CAAC;AACxI,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjC;;;GAGG;AACH,qBAEa,WAAY,SAAQ,SAAS,CAAC,WAAW,CAAC;IACrD,YAAmB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAG7C;IAED;;OAEG;IAGI,EAAE,EAAG,MAAM,CAAC;IAEnB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;OAEG;IACI,IAAI,EAAG,MAAM,CAAC;IAErB;;;OAGG;IAEI,KAAK,EAAG,MAAM,CAAC;IAEtB;;;OAGG;IAEI,KAAK,EAAG,MAAM,EAAE,CAAC;IAExB;;;;;;;OAOG;IAEI,SAAS,CAAC,EAAE,QAAQ,CAAC;IAGrB,SAAS,EAAG,QAAQ,CAAC;IAE5B;;;;OAIG;IAEI,UAAU,CAAC,EAAE,QAAQ,CAAC;IAItB,IAAI,EAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAG5B,OAAO,EAAG,MAAM,CAAC;IAExB;;OAEG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;CACF"}
@@ -0,0 +1,70 @@
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 { BelongsTo, Connection, CreatedAt, DateTime as DT, Hidden, Model, ModelBase, Primary, Set, SingleRelation } from '@spinajs/orm';
11
+ import { DateTime } from 'luxon';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import { _check_arg, _default } from '@spinajs/util';
14
+ /**
15
+ * Personal access token. Only the SHA-256 hash of the token is stored;
16
+ * the plaintext is returned once at creation and cannot be recovered.
17
+ */
18
+ let AccessToken = class AccessToken extends ModelBase {
19
+ constructor(data) {
20
+ super(data);
21
+ this.Uuid = _check_arg(_default(uuidv4()))(this.Uuid, 'uuid');
22
+ }
23
+ /**
24
+ * True when the token carries an expiration in the past.
25
+ */
26
+ get IsExpired() {
27
+ return !!this.ExpiresAt && this.ExpiresAt <= DateTime.now();
28
+ }
29
+ };
30
+ __decorate([
31
+ Primary(),
32
+ Hidden(),
33
+ __metadata("design:type", Number)
34
+ ], AccessToken.prototype, "Id", void 0);
35
+ __decorate([
36
+ Hidden(),
37
+ __metadata("design:type", String)
38
+ ], AccessToken.prototype, "Token", void 0);
39
+ __decorate([
40
+ Set(),
41
+ __metadata("design:type", Array)
42
+ ], AccessToken.prototype, "Roles", void 0);
43
+ __decorate([
44
+ DT(),
45
+ __metadata("design:type", DateTime)
46
+ ], AccessToken.prototype, "ExpiresAt", void 0);
47
+ __decorate([
48
+ CreatedAt(),
49
+ __metadata("design:type", DateTime)
50
+ ], AccessToken.prototype, "CreatedAt", void 0);
51
+ __decorate([
52
+ DT(),
53
+ __metadata("design:type", DateTime)
54
+ ], AccessToken.prototype, "LastUsedAt", void 0);
55
+ __decorate([
56
+ Hidden(),
57
+ BelongsTo('User'),
58
+ __metadata("design:type", SingleRelation)
59
+ ], AccessToken.prototype, "User", void 0);
60
+ __decorate([
61
+ Hidden(),
62
+ __metadata("design:type", Number)
63
+ ], AccessToken.prototype, "user_id", void 0);
64
+ AccessToken = __decorate([
65
+ Connection('default'),
66
+ Model('rbac_access_tokens'),
67
+ __metadata("design:paramtypes", [Object])
68
+ ], AccessToken);
69
+ export { AccessToken };
70
+ //# sourceMappingURL=AccessToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AccessToken.js","sourceRoot":"","sources":["../../../src/models/AccessToken.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAExI,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAErD;;;GAGG;AAGI,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,SAAsB;IACrD,YAAmB,IAA2B;QAC5C,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChE,CAAC;IA8DD;;OAEG;IACH,IAAW,SAAS;QAClB,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;IAC9D,CAAC;CACF,CAAA;AA7DQ;IAFN,OAAO,EAAE;IACT,MAAM,EAAE;;uCACU;AAiBZ;IADN,MAAM,EAAE;;0CACa;AAOf;IADN,GAAG,EAAE;;0CACkB;AAWjB;IADN,EAAE,EAAE;8BACc,QAAQ;8CAAC;AAGrB;IADN,SAAS,EAAE;8BACO,QAAQ;8CAAC;AAQrB;IADN,EAAE,EAAE;8BACe,QAAQ;+CAAC;AAItB;IAFN,MAAM,EAAE;IACR,SAAS,CAAC,MAAM,CAAC;8BACJ,cAAc;yCAAO;AAG5B;IADN,MAAM,EAAE;;4CACe;AAhEb,WAAW;IAFvB,UAAU,CAAC,SAAS,CAAC;IACrB,KAAK,CAAC,oBAAoB,CAAC;;GACf,WAAW,CAwEvB"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,28 @@
1
+ import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
2
+ import '../interfaces.js';
3
+ /**
4
+ * Rejects requests made from an impersonated session.
5
+ *
6
+ * Impersonation is a *supervised, revocable* act: an administrator borrows a
7
+ * user's view of the application and the borrowing ends when the impersonation
8
+ * does. An access token is the opposite - a bearer credential that outlives the
9
+ * session that minted it, carries the victim's roles, and is invisible in the
10
+ * impersonator's own audit trail. Letting a credential-issuing route run while
11
+ * impersonating therefore turns a temporary, reversible grant into a permanent
12
+ * one that the account owner never consented to and cannot see.
13
+ *
14
+ * `RbacMiddleware` puts the impersonation TARGET in `req.storage.User` and the
15
+ * original administrator in `req.storage.Impersonator`
16
+ * ( `rbac-http/src/middlewares.ts` ), so every ownership and permission check
17
+ * downstream already reads as the victim - this policy is the only thing that
18
+ * can tell the two situations apart.
19
+ *
20
+ * Same reasoning as a password change demanding the CURRENT password: an
21
+ * operation that hands out lasting credentials has to be performed by the
22
+ * account owner, not on their behalf.
23
+ */
24
+ export declare class NoImpersonationPolicy extends BasePolicy {
25
+ isEnabled(_action: IRoute, _instance: IController): boolean;
26
+ execute(req: sRequest, _action: IRoute, _instance: IController): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=NoImpersonationPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoImpersonationPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/NoImpersonationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQrF,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,qBAAsB,SAAQ,UAAU;IAC5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;CACF"}
@@ -0,0 +1,41 @@
1
+ import { BasePolicy } from '@spinajs/http';
2
+ import { Forbidden } from '@spinajs/exceptions';
3
+ // Same side-effect import both siblings carry. `req.storage.Impersonator` comes
4
+ // from `@spinajs/rbac-http`'s augmentation of `IActionLocalStoregeContext`,
5
+ // which this package's `interfaces.ts` pulls into the program ( type-only ).
6
+ // Without it the field only type-checks when something ELSE in the compilation
7
+ // happened to drag that augmentation in - fine today, silently broken the day
8
+ // this file is compiled on its own.
9
+ import '../interfaces.js';
10
+ /**
11
+ * Rejects requests made from an impersonated session.
12
+ *
13
+ * Impersonation is a *supervised, revocable* act: an administrator borrows a
14
+ * user's view of the application and the borrowing ends when the impersonation
15
+ * does. An access token is the opposite - a bearer credential that outlives the
16
+ * session that minted it, carries the victim's roles, and is invisible in the
17
+ * impersonator's own audit trail. Letting a credential-issuing route run while
18
+ * impersonating therefore turns a temporary, reversible grant into a permanent
19
+ * one that the account owner never consented to and cannot see.
20
+ *
21
+ * `RbacMiddleware` puts the impersonation TARGET in `req.storage.User` and the
22
+ * original administrator in `req.storage.Impersonator`
23
+ * ( `rbac-http/src/middlewares.ts` ), so every ownership and permission check
24
+ * downstream already reads as the victim - this policy is the only thing that
25
+ * can tell the two situations apart.
26
+ *
27
+ * Same reasoning as a password change demanding the CURRENT password: an
28
+ * operation that hands out lasting credentials has to be performed by the
29
+ * account owner, not on their behalf.
30
+ */
31
+ export class NoImpersonationPolicy extends BasePolicy {
32
+ isEnabled(_action, _instance) {
33
+ return true;
34
+ }
35
+ async execute(req, _action, _instance) {
36
+ if (req.storage?.Impersonator) {
37
+ throw new Forbidden('this route cannot be used while impersonating another user');
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=NoImpersonationPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoImpersonationPolicy.js","sourceRoot":"","sources":["../../../src/policies/NoImpersonationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,gFAAgF;AAChF,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,oCAAoC;AACpC,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,qBAAsB,SAAQ,UAAU;IAC5C,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,OAAe,EAAE,SAAsB;QACzE,IAAI,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;YAC9B,MAAM,IAAI,SAAS,CAAC,4DAA4D,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
2
+ import '../interfaces.js';
3
+ /**
4
+ * Rejects requests authenticated with an access token. Applied to the token
5
+ * management API so a token can never be used to mint or manage tokens
6
+ * ( no self-replication ). Session-authenticated requests pass through.
7
+ */
8
+ export declare class NoTokenAuthPolicy extends BasePolicy {
9
+ isEnabled(_action: IRoute, _instance: IController): boolean;
10
+ execute(req: sRequest, _action: IRoute, _instance: IController): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=NoTokenAuthPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoTokenAuthPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/NoTokenAuthPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGrF,OAAO,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IACxC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1F;CACF"}
@@ -0,0 +1,20 @@
1
+ import { BasePolicy } from '@spinajs/http';
2
+ import { Forbidden } from '@spinajs/exceptions';
3
+ // Brings the `req.storage.TokenAuth` module augmentation into the program.
4
+ import '../interfaces.js';
5
+ /**
6
+ * Rejects requests authenticated with an access token. Applied to the token
7
+ * management API so a token can never be used to mint or manage tokens
8
+ * ( no self-replication ). Session-authenticated requests pass through.
9
+ */
10
+ export class NoTokenAuthPolicy extends BasePolicy {
11
+ isEnabled(_action, _instance) {
12
+ return true;
13
+ }
14
+ async execute(req, _action, _instance) {
15
+ if (req.storage?.TokenAuth) {
16
+ throw new Forbidden('access tokens cannot be used on this route');
17
+ }
18
+ }
19
+ }
20
+ //# sourceMappingURL=NoTokenAuthPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoTokenAuthPolicy.js","sourceRoot":"","sources":["../../../src/policies/NoTokenAuthPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,2EAA2E;AAC3E,OAAO,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IACxC,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,OAAe,EAAE,SAAsB;QACzE,IAAI,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,49 @@
1
+ import { BasePolicy, IController, IRoute, Request as sRequest } from '@spinajs/http';
2
+ import '../interfaces.js';
3
+ /**
4
+ * Route requires authentication with an access token AND the token's
5
+ * effective roles must satisfy the route's @Resource/@Permission grants.
6
+ *
7
+ * Mirrors RbacPolicy's grant enforcement, but for token-authenticated
8
+ * requests ( which carry no session ).
9
+ *
10
+ * WIRING - do NOT pass this policy to @Permission's `also` parameter:
11
+ *
12
+ * @Permission(['readOwn'], TokenPolicy) // BROKEN - always 401
13
+ *
14
+ * `@Permission` unconditionally bundles RbacPolicy together with every `also`
15
+ * policy into the SAME policy group ( rbac-http/src/decorators.ts ), and
16
+ * policies inside one group are combined with AND. RbacPolicy demands an
17
+ * authorized session, which a token-authenticated request never has, so the
18
+ * pair can never both pass and the route is permanently unreachable by token.
19
+ *
20
+ * Declare it as its OWN group at the ROUTE scope instead - groups of ONE scope
21
+ * are ORed, so a token request satisfies the TokenPolicy group while a session
22
+ * request satisfies the RbacPolicy group:
23
+ *
24
+ * @Get('data')
25
+ * @Permission(['readOwn']) // the permission metadata + RbacPolicy group
26
+ * @Policy(TokenPolicy) // METHOD level - a second route scope group
27
+ *
28
+ * The placement is not free-standing: a CLASS level `@Policy(TokenPolicy)` goes
29
+ * to the CONTROLLER scope, and the two scopes are ANDed - it would then have to
30
+ * hold TOGETHER with the route's RbacPolicy group, which is exactly the broken
31
+ * combination above. Only a method level declaration lands in the same scope as
32
+ * `@Permission` and gets ORed with it.
33
+ *
34
+ * Writing `@Policy(TokenPolicy)` BELOW `@Permission` is deliberate too.
35
+ * Decorators apply bottom up, so this one is pushed first, and when no group
36
+ * holds `createPolicyGate` reports the first rejection in declaration order: a
37
+ * token that authenticated but lacks the grant then gets this policy's 403
38
+ * instead of RbacPolicy's misleading "user not logged" 401.
39
+ *
40
+ * The `@Permission` line is still required even with `@Policy(TokenPolicy)`:
41
+ * this policy reads the same route permission metadata, and a route without it
42
+ * silently inherits the controller-level default `['readOwn']` rather than
43
+ * failing loudly.
44
+ */
45
+ export declare class TokenPolicy extends BasePolicy {
46
+ isEnabled(_action: IRoute, _instance: IController): boolean;
47
+ execute(req: sRequest, action: IRoute, instance: IController): Promise<void>;
48
+ }
49
+ //# sourceMappingURL=TokenPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenPolicy.d.ts","sourceRoot":"","sources":["../../../src/policies/TokenPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAe,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMlG,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,WAAY,SAAQ,UAAU;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,GAAG,OAAO,CAEjE;IAEY,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBxF;CACF"}
@@ -0,0 +1,75 @@
1
+ import { BasePolicy, ServerError } from '@spinajs/http';
2
+ import { AuthenticationFailed, Forbidden } from '@spinajs/exceptions';
3
+ import { ACL_CONTROLLER_DESCRIPTOR, checkRoutePermission } from '@spinajs/rbac-http';
4
+ // Brings the `req.storage.TokenAuth` module augmentation into the program.
5
+ // Same side-effect import the middleware uses; without it this file compiles
6
+ // on its own against an un-augmented IActionLocalStoregeContext.
7
+ import '../interfaces.js';
8
+ /**
9
+ * Route requires authentication with an access token AND the token's
10
+ * effective roles must satisfy the route's @Resource/@Permission grants.
11
+ *
12
+ * Mirrors RbacPolicy's grant enforcement, but for token-authenticated
13
+ * requests ( which carry no session ).
14
+ *
15
+ * WIRING - do NOT pass this policy to @Permission's `also` parameter:
16
+ *
17
+ * @Permission(['readOwn'], TokenPolicy) // BROKEN - always 401
18
+ *
19
+ * `@Permission` unconditionally bundles RbacPolicy together with every `also`
20
+ * policy into the SAME policy group ( rbac-http/src/decorators.ts ), and
21
+ * policies inside one group are combined with AND. RbacPolicy demands an
22
+ * authorized session, which a token-authenticated request never has, so the
23
+ * pair can never both pass and the route is permanently unreachable by token.
24
+ *
25
+ * Declare it as its OWN group at the ROUTE scope instead - groups of ONE scope
26
+ * are ORed, so a token request satisfies the TokenPolicy group while a session
27
+ * request satisfies the RbacPolicy group:
28
+ *
29
+ * @Get('data')
30
+ * @Permission(['readOwn']) // the permission metadata + RbacPolicy group
31
+ * @Policy(TokenPolicy) // METHOD level - a second route scope group
32
+ *
33
+ * The placement is not free-standing: a CLASS level `@Policy(TokenPolicy)` goes
34
+ * to the CONTROLLER scope, and the two scopes are ANDed - it would then have to
35
+ * hold TOGETHER with the route's RbacPolicy group, which is exactly the broken
36
+ * combination above. Only a method level declaration lands in the same scope as
37
+ * `@Permission` and gets ORed with it.
38
+ *
39
+ * Writing `@Policy(TokenPolicy)` BELOW `@Permission` is deliberate too.
40
+ * Decorators apply bottom up, so this one is pushed first, and when no group
41
+ * holds `createPolicyGate` reports the first rejection in declaration order: a
42
+ * token that authenticated but lacks the grant then gets this policy's 403
43
+ * instead of RbacPolicy's misleading "user not logged" 401.
44
+ *
45
+ * The `@Permission` line is still required even with `@Policy(TokenPolicy)`:
46
+ * this policy reads the same route permission metadata, and a route without it
47
+ * silently inherits the controller-level default `['readOwn']` rather than
48
+ * failing loudly.
49
+ */
50
+ export class TokenPolicy extends BasePolicy {
51
+ isEnabled(_action, _instance) {
52
+ return true;
53
+ }
54
+ async execute(req, action, instance) {
55
+ if (!req.storage || !req.storage.TokenAuth || !req.storage.User) {
56
+ throw new AuthenticationFailed('access token required');
57
+ }
58
+ const descriptor = Reflect.getMetadata(ACL_CONTROLLER_DESCRIPTOR, instance);
59
+ // Guard BEFORE dereferencing `.Routes`: a route decorated with this policy
60
+ // but no @Resource/@Permission must produce the descriptive server error,
61
+ // not a raw TypeError 500.
62
+ if (!descriptor || !descriptor.Permission || descriptor.Permission.length === 0) {
63
+ throw new ServerError('no route permission or resources assigned');
64
+ }
65
+ let permission = descriptor.Permission ?? [];
66
+ if (descriptor.Routes.has(String(action.Method))) {
67
+ permission = descriptor.Routes.get(String(action.Method)).Permission ?? [];
68
+ }
69
+ if (!permission.some((p) => checkRoutePermission(req, descriptor.Resource, p)?.granted)) {
70
+ const effective = req.storage.ActiveRole ?? req.storage.User.Role;
71
+ throw new Forbidden(`token role(s) ${effective} do not have permission ${permission} for resource ${descriptor.Resource}`);
72
+ }
73
+ }
74
+ }
75
+ //# sourceMappingURL=TokenPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenPolicy.js","sourceRoot":"","sources":["../../../src/policies/TokenPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAuB,WAAW,EAAuB,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACtG,2EAA2E;AAC3E,6EAA6E;AAC7E,iEAAiE;AACjE,OAAO,kBAAkB,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,OAAO,WAAY,SAAQ,UAAU;IAClC,SAAS,CAAC,OAAe,EAAE,SAAsB;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,GAAa,EAAE,MAAc,EAAE,QAAqB;QACvE,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAChE,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,UAAU,GAAoB,OAAO,CAAC,WAAW,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;QAE7F,2EAA2E;QAC3E,0EAA0E;QAC1E,2BAA2B;QAC3B,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChF,MAAM,IAAI,WAAW,CAAC,2CAA2C,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,UAAU,GAAG,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC;QAC7C,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACjD,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAE,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;YACxF,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAClE,MAAM,IAAI,SAAS,CAAC,iBAAiB,SAAS,2BAA2B,UAAU,iBAAiB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7H,CAAC;IACH,CAAC;CACF"}