@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,42 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SecureRandomTokenProvider = void 0;
13
+ const crypto_1 = require("crypto");
14
+ const di_1 = require("@spinajs/di");
15
+ const configuration_1 = require("@spinajs/configuration");
16
+ const interfaces_js_1 = require("./interfaces.js");
17
+ /**
18
+ * Default token algorithm: `<prefix>` + N crypto-random bytes base64url encoded.
19
+ * The stable prefix makes leaked tokens findable by secret scanners.
20
+ */
21
+ let SecureRandomTokenProvider = class SecureRandomTokenProvider extends interfaces_js_1.AccessTokenGenerationProvider {
22
+ async generate() {
23
+ const plaintext = `${this.Prefix}${(0, crypto_1.randomBytes)(this.Length).toString('base64url')}`;
24
+ return { Plaintext: plaintext, Hash: this.hash(plaintext) };
25
+ }
26
+ hash(plaintext) {
27
+ return (0, crypto_1.createHash)('sha256').update(plaintext).digest('hex');
28
+ }
29
+ };
30
+ exports.SecureRandomTokenProvider = SecureRandomTokenProvider;
31
+ __decorate([
32
+ (0, configuration_1.Config)('rbac.token.prefix', { defaultValue: 'spt_' }),
33
+ __metadata("design:type", String)
34
+ ], SecureRandomTokenProvider.prototype, "Prefix", void 0);
35
+ __decorate([
36
+ (0, configuration_1.Config)('rbac.token.length', { defaultValue: 32 }),
37
+ __metadata("design:type", Number)
38
+ ], SecureRandomTokenProvider.prototype, "Length", void 0);
39
+ exports.SecureRandomTokenProvider = SecureRandomTokenProvider = __decorate([
40
+ (0, di_1.Injectable)(interfaces_js_1.AccessTokenGenerationProvider)
41
+ ], SecureRandomTokenProvider);
42
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/generator.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,mCAAiD;AACjD,oCAAyC;AACzC,0DAAgD;AAEhD,mDAAiF;AAEjF;;;GAGG;AAEI,IAAM,yBAAyB,GAA/B,MAAM,yBAA0B,SAAQ,6CAA6B;IAOnE,KAAK,CAAC,QAAQ;QACnB,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,IAAA,oBAAW,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACpF,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;IAC9D,CAAC;IAEM,IAAI,CAAC,SAAiB;QAC3B,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC;CACF,CAAA;;AAbW;IADT,IAAA,sBAAM,EAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;;yDAC7B;AAGf;IADT,IAAA,sBAAM,EAAC,mBAAmB,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;;yDACzB;oCALd,yBAAyB;IADrC,IAAA,eAAU,EAAC,6CAA6B,CAAC;GAC7B,yBAAyB,CAerC"}
@@ -0,0 +1,20 @@
1
+ import './generator.js';
2
+ import './middlewares.js';
3
+ export * from './interfaces.js';
4
+ export * from './models/AccessToken.js';
5
+ export * from './migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js';
6
+ export * from './generator.js';
7
+ export * from './events/index.js';
8
+ export * from './actions.js';
9
+ export * from './middlewares.js';
10
+ export * from './policies/TokenPolicy.js';
11
+ export * from './policies/NoTokenAuthPolicy.js';
12
+ export * from './policies/NoImpersonationPolicy.js';
13
+ export * from './controllers/AccessTokenController.js';
14
+ export * from './dto/create-token-dto.js';
15
+ export * from './cli/CreateToken.js';
16
+ export * from './cli/DeleteToken.js';
17
+ export * from './cli/GrantTokenRole.js';
18
+ export * from './cli/RevokeTokenRole.js';
19
+ export * from './cli/DeleteExpiredTokens.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,gBAAgB,CAAC;AACxB,OAAO,kBAAkB,CAAC;AAE1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0DAA0D,CAAC;AACzE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,wCAAwC,CAAC;AACvD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Side effect imports - these modules register Injectables ( the token
18
+ // generator and the token authorization middleware ) the moment they are
19
+ // loaded, so they must run even if a consumer imports nothing from them.
20
+ require("./generator.js");
21
+ require("./middlewares.js");
22
+ __exportStar(require("./interfaces.js"), exports);
23
+ __exportStar(require("./models/AccessToken.js"), exports);
24
+ __exportStar(require("./migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.js"), exports);
25
+ __exportStar(require("./generator.js"), exports);
26
+ __exportStar(require("./events/index.js"), exports);
27
+ __exportStar(require("./actions.js"), exports);
28
+ __exportStar(require("./middlewares.js"), exports);
29
+ __exportStar(require("./policies/TokenPolicy.js"), exports);
30
+ __exportStar(require("./policies/NoTokenAuthPolicy.js"), exports);
31
+ __exportStar(require("./policies/NoImpersonationPolicy.js"), exports);
32
+ __exportStar(require("./controllers/AccessTokenController.js"), exports);
33
+ __exportStar(require("./dto/create-token-dto.js"), exports);
34
+ __exportStar(require("./cli/CreateToken.js"), exports);
35
+ __exportStar(require("./cli/DeleteToken.js"), exports);
36
+ __exportStar(require("./cli/GrantTokenRole.js"), exports);
37
+ __exportStar(require("./cli/RevokeTokenRole.js"), exports);
38
+ __exportStar(require("./cli/DeleteExpiredTokens.js"), exports);
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uEAAuE;AACvE,yEAAyE;AACzE,yEAAyE;AACzE,0BAAwB;AACxB,4BAA0B;AAE1B,kDAAgC;AAChC,0DAAwC;AACxC,2FAAyE;AACzE,iDAA+B;AAC/B,oDAAkC;AAClC,+CAA6B;AAC7B,mDAAiC;AACjC,4DAA0C;AAC1C,kEAAgD;AAChD,sEAAoD;AACpD,yEAAuD;AACvD,4DAA0C;AAC1C,uDAAqC;AACrC,uDAAqC;AACrC,0DAAwC;AACxC,2DAAyC;AACzC,+DAA6C"}
@@ -0,0 +1,57 @@
1
+ export interface IGeneratedToken {
2
+ /**
3
+ * Full token as handed to the user, e.g. `spt_<base64url>`. Shown exactly once.
4
+ */
5
+ Plaintext: string;
6
+ /**
7
+ * SHA-256 hex digest of the plaintext - the only thing that is persisted.
8
+ */
9
+ Hash: string;
10
+ }
11
+ /**
12
+ * Token generation algorithm. Replaceable via config
13
+ * `rbac.token.generation.service` - same pattern as `rbac.password.service`.
14
+ */
15
+ export declare abstract class AccessTokenGenerationProvider {
16
+ /**
17
+ * Generates a fresh token. Plaintext leaves the server once; only the hash is stored.
18
+ */
19
+ abstract generate(): Promise<IGeneratedToken>;
20
+ /**
21
+ * Deterministic hash of a presented plaintext, used for DB lookup.
22
+ */
23
+ abstract hash(plaintext: string): string;
24
+ }
25
+ /**
26
+ * Marker stored on request async storage when a request was authenticated
27
+ * with an access token instead of a session.
28
+ */
29
+ export interface ITokenAuthInfo {
30
+ /**
31
+ * Uuid of the AccessToken row - safe to log; never the token itself.
32
+ */
33
+ Uuid: string;
34
+ }
35
+ declare module '@spinajs/rbac' {
36
+ interface IRbacAsyncStorage {
37
+ /**
38
+ * Set by TokenAuthMiddleware when the request carries a valid access token.
39
+ */
40
+ TokenAuth?: ITokenAuthInfo;
41
+ }
42
+ }
43
+ /**
44
+ * The http request-local storage is a SEPARATE interface from rbac's
45
+ * `IRbacAsyncStorage` ( `@spinajs/rbac-http` augments it the same way with
46
+ * User / Session / ActiveRole ), so the marker has to be declared on both -
47
+ * the one above for rbac's execution context, this one for `req.storage`.
48
+ */
49
+ declare module '@spinajs/http' {
50
+ interface IActionLocalStoregeContext {
51
+ /**
52
+ * Set by TokenAuthMiddleware when the request carries a valid access token.
53
+ */
54
+ TokenAuth?: ITokenAuthInfo;
55
+ }
56
+ }
57
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,8BAAsB,6BAA6B;IACjD;;OAEG;IACH,SAAgB,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IAErD;;OAEG;IACH,SAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,iBAAiB;QACzB;;WAEG;QACH,SAAS,CAAC,EAAE,cAAc,CAAC;KAC5B;CACF;AAED;;;;;GAKG;AACH,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,0BAA0B;QAClC;;WAEG;QACH,SAAS,CAAC,EAAE,cAAc,CAAC;KAC5B;CACF"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AccessTokenGenerationProvider = void 0;
4
+ /**
5
+ * Token generation algorithm. Replaceable via config
6
+ * `rbac.token.generation.service` - same pattern as `rbac.password.service`.
7
+ */
8
+ class AccessTokenGenerationProvider {
9
+ }
10
+ exports.AccessTokenGenerationProvider = AccessTokenGenerationProvider;
11
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":";;;AAsBA;;;GAGG;AACH;CAUC"}
@@ -0,0 +1,76 @@
1
+ import * as express from 'express';
2
+ import { Log } from '@spinajs/log';
3
+ import { Request as sRequest, ServerMiddleware } from '@spinajs/http';
4
+ import { User } from '@spinajs/rbac';
5
+ import './interfaces.js';
6
+ /**
7
+ * Authenticates requests carrying an access token in `Authorization: Bearer`
8
+ * or the configured fallback header. Runs AFTER RbacMiddleware ( Order 0 )
9
+ * so a session, when present, always wins - a request cannot mix both.
10
+ *
11
+ * On success `req.storage.User` carries the owner with Role narrowed to the
12
+ * token's effective roles, so every downstream permission check ( RbacPolicy
13
+ * helpers, orm rbac query middleware, ownership ) works unchanged.
14
+ *
15
+ * `req.storage.ActiveRole` is deliberately CLEARED, and that is load bearing.
16
+ * Both consumers of the field resolve the roles to authorize with as
17
+ * `ActiveRole ? [ActiveRole] : User.Role` ( `checkRoutePermission` in
18
+ * `rbac-http/src/policies/RbacPolicy.ts`, and the orm rbac query middleware in
19
+ * `rbac/src/middleware.ts` ), so whatever single role sits there collapses the
20
+ * request down to that one role.
21
+ *
22
+ * A session can afford that collapse because it can switch its active role at
23
+ * runtime ( `POST /auth/active-role` ), so the narrowing is both deliberate and
24
+ * reversible. A token carries no session and has no way to switch, so picking
25
+ * one of its roles - the first, arbitrarily - would permanently authorize the
26
+ * token with a strict subset of what it was issued for: a token holding
27
+ * `[ 'user', 'admin' ]` would never satisfy an admin-only grant.
28
+ *
29
+ * Leaving it undefined makes both consumers fall back to `User.Role`, which the
30
+ * narrowing above has ALREADY reduced to exactly the effective role set - the
31
+ * intersection of what the token carries and its owner still holds. That is the
32
+ * correct authorization scope for a token, and nothing wider.
33
+ *
34
+ * The field has to be assigned `undefined` rather than skipped: `RbacMiddleware`
35
+ * runs first and, on a session-less request, stamps the GUEST account's first
36
+ * role into it, which would otherwise survive into the token's own request.
37
+ *
38
+ * Never throws: an invalid token leaves the request as guest and lets the
39
+ * route's policy produce the rejection.
40
+ */
41
+ export declare class TokenAuthMiddleware extends ServerMiddleware {
42
+ protected Log: Log;
43
+ protected HeaderName: string;
44
+ protected LastUsedUpdateInterval: number;
45
+ constructor();
46
+ before(): (req: sRequest, res: express.Response, next: express.NextFunction) => void;
47
+ after(): null;
48
+ /**
49
+ * Narrows the loaded owner to the token's effective roles WITHOUT letting the
50
+ * narrowing reach the database.
51
+ *
52
+ * `Role` is a real `@Set()` column, and this very instance is what controllers
53
+ * receive through the `@User()` route argument. `update()` writes whatever
54
+ * differs from the model's snapshot, so a controller doing an unrelated edit
55
+ * ( "change my login" ) and calling `.update()` would silently persist the
56
+ * narrowed list - permanently stripping every role the token did not carry.
57
+ *
58
+ * Re-taking the snapshot right after the narrowing makes it invisible to that
59
+ * diff: the instance then behaves exactly like a freshly loaded row whose roles
60
+ * happen to be the effective ones, and a later `.update()` writes only what the
61
+ * controller itself changed. The full instance is kept rather than copied so
62
+ * that `Id`, `Password`, the `Metadata` relation and the prototype accessors
63
+ * ( `IsBanned`, `can()` ) all survive - `dehydrate()` drops the `@Hidden()`
64
+ * columns, so a dehydrate/rehydrate copy would arrive without `Id`.
65
+ *
66
+ * `takeSnapshot()` also discards the relation baselines, which the orm's
67
+ * subject builder needs to tell an already-persisted related row from a new
68
+ * one, so they are recorded again immediately.
69
+ */
70
+ protected narrowRoles(user: User, roles: string[]): User;
71
+ /**
72
+ * Bearer scheme first, configured fallback header second.
73
+ */
74
+ protected extract(req: sRequest): string | null;
75
+ }
76
+ //# sourceMappingURL=middlewares.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,GAAG,EAAU,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC,OAAO,iBAAiB,CAAC;AAQzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBACa,mBAAoB,SAAQ,gBAAgB;IAEvD,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC;IAGnB,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC;IAG7B,SAAS,CAAC,sBAAsB,EAAE,MAAM,CAAC;IAEzC,cAIC;IAEM,MAAM,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI,CAkD1F;IAEM,KAAK,IAAI,IAAI,CAEnB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CASvD;IAED;;OAEG;IACH,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAgB9C;CACF"}
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TokenAuthMiddleware = void 0;
13
+ const di_1 = require("@spinajs/di");
14
+ const configuration_1 = require("@spinajs/configuration");
15
+ const log_1 = require("@spinajs/log");
16
+ const http_1 = require("@spinajs/http");
17
+ const exceptions_1 = require("@spinajs/exceptions");
18
+ const actions_js_1 = require("./actions.js");
19
+ require("./interfaces.js");
20
+ /**
21
+ * `Authorization: Bearer <token>`. RFC 7235 makes the scheme name
22
+ * case-insensitive, and clients do send `bearer`.
23
+ */
24
+ const BEARER_SCHEME = /^bearer\s+/i;
25
+ /**
26
+ * Authenticates requests carrying an access token in `Authorization: Bearer`
27
+ * or the configured fallback header. Runs AFTER RbacMiddleware ( Order 0 )
28
+ * so a session, when present, always wins - a request cannot mix both.
29
+ *
30
+ * On success `req.storage.User` carries the owner with Role narrowed to the
31
+ * token's effective roles, so every downstream permission check ( RbacPolicy
32
+ * helpers, orm rbac query middleware, ownership ) works unchanged.
33
+ *
34
+ * `req.storage.ActiveRole` is deliberately CLEARED, and that is load bearing.
35
+ * Both consumers of the field resolve the roles to authorize with as
36
+ * `ActiveRole ? [ActiveRole] : User.Role` ( `checkRoutePermission` in
37
+ * `rbac-http/src/policies/RbacPolicy.ts`, and the orm rbac query middleware in
38
+ * `rbac/src/middleware.ts` ), so whatever single role sits there collapses the
39
+ * request down to that one role.
40
+ *
41
+ * A session can afford that collapse because it can switch its active role at
42
+ * runtime ( `POST /auth/active-role` ), so the narrowing is both deliberate and
43
+ * reversible. A token carries no session and has no way to switch, so picking
44
+ * one of its roles - the first, arbitrarily - would permanently authorize the
45
+ * token with a strict subset of what it was issued for: a token holding
46
+ * `[ 'user', 'admin' ]` would never satisfy an admin-only grant.
47
+ *
48
+ * Leaving it undefined makes both consumers fall back to `User.Role`, which the
49
+ * narrowing above has ALREADY reduced to exactly the effective role set - the
50
+ * intersection of what the token carries and its owner still holds. That is the
51
+ * correct authorization scope for a token, and nothing wider.
52
+ *
53
+ * The field has to be assigned `undefined` rather than skipped: `RbacMiddleware`
54
+ * runs first and, on a session-less request, stamps the GUEST account's first
55
+ * role into it, which would otherwise survive into the token's own request.
56
+ *
57
+ * Never throws: an invalid token leaves the request as guest and lets the
58
+ * route's policy produce the rejection.
59
+ */
60
+ let TokenAuthMiddleware = class TokenAuthMiddleware extends http_1.ServerMiddleware {
61
+ constructor() {
62
+ super();
63
+ // After RbacMiddleware ( Order 0 ): session auth takes precedence.
64
+ this.Order = 1;
65
+ }
66
+ before() {
67
+ return async (req, res, next) => {
68
+ try {
69
+ // Session user already authenticated - tokens do not apply.
70
+ if (req.storage?.Session) {
71
+ return next();
72
+ }
73
+ const plaintext = this.extract(req);
74
+ if (!plaintext) {
75
+ return next();
76
+ }
77
+ let result;
78
+ try {
79
+ result = await (0, actions_js_1.validateToken)(plaintext);
80
+ }
81
+ catch (err) {
82
+ // Deliberately vague towards the client; specific in the log. The uuid
83
+ // is what makes a rejection actionable ( "which key broke" ) and is
84
+ // safe to write down - `validateToken` attaches it as `data.token` on
85
+ // every failure past the lookup. The presented plaintext is NEVER
86
+ // logged, here or anywhere else.
87
+ const data = err instanceof exceptions_1.ErrorCode ? err.data : undefined;
88
+ this.Log.warn(`Access token rejected: ${err.message}`, { Ip: req.ip, Token: data?.token });
89
+ return next();
90
+ }
91
+ req.storage.User = this.narrowRoles(result.User, result.EffectiveRoles);
92
+ req.storage.TokenAuth = { Uuid: result.Token.Uuid };
93
+ // CLEARED, not merely left alone - see the class docblock for why a
94
+ // token must carry no active role at all. `RbacMiddleware` has already
95
+ // run by now and, finding no session, wrote the GUEST user's first role
96
+ // here ( `rbac-http/src/middlewares.ts`, the `else` branch ). Leaving
97
+ // that in place would authorize every token request as `guest`.
98
+ req.storage.ActiveRole = undefined;
99
+ // Token-authenticated responses must never land in a shared cache.
100
+ res.setHeader('Cache-Control', 'no-store');
101
+ // Fire-and-forget throttled usage stamp. A non-Error rejection has no
102
+ // `.message`; reading one off it would throw inside the handler and
103
+ // surface as an unhandled rejection.
104
+ void (0, actions_js_1.touchToken)(result.Token, this.LastUsedUpdateInterval).catch((err) => this.Log.warn(`Failed to update token LastUsedAt: ${err instanceof Error ? err.message : String(err)}`, { Token: result.Token.Uuid }));
105
+ next();
106
+ }
107
+ catch (err) {
108
+ next(err);
109
+ }
110
+ };
111
+ }
112
+ after() {
113
+ return null;
114
+ }
115
+ /**
116
+ * Narrows the loaded owner to the token's effective roles WITHOUT letting the
117
+ * narrowing reach the database.
118
+ *
119
+ * `Role` is a real `@Set()` column, and this very instance is what controllers
120
+ * receive through the `@User()` route argument. `update()` writes whatever
121
+ * differs from the model's snapshot, so a controller doing an unrelated edit
122
+ * ( "change my login" ) and calling `.update()` would silently persist the
123
+ * narrowed list - permanently stripping every role the token did not carry.
124
+ *
125
+ * Re-taking the snapshot right after the narrowing makes it invisible to that
126
+ * diff: the instance then behaves exactly like a freshly loaded row whose roles
127
+ * happen to be the effective ones, and a later `.update()` writes only what the
128
+ * controller itself changed. The full instance is kept rather than copied so
129
+ * that `Id`, `Password`, the `Metadata` relation and the prototype accessors
130
+ * ( `IsBanned`, `can()` ) all survive - `dehydrate()` drops the `@Hidden()`
131
+ * columns, so a dehydrate/rehydrate copy would arrive without `Id`.
132
+ *
133
+ * `takeSnapshot()` also discards the relation baselines, which the orm's
134
+ * subject builder needs to tell an already-persisted related row from a new
135
+ * one, so they are recorded again immediately.
136
+ */
137
+ narrowRoles(user, roles) {
138
+ user.Role = roles;
139
+ user.takeSnapshot();
140
+ for (const [name] of user.ModelDescriptor?.Relations ?? []) {
141
+ user.snapshotRelation(name);
142
+ }
143
+ return user;
144
+ }
145
+ /**
146
+ * Bearer scheme first, configured fallback header second.
147
+ */
148
+ extract(req) {
149
+ // A header sent twice arrives as an array. Anything that is not a single
150
+ // string is malformed and has to read as "no token presented" - calling
151
+ // `.startsWith` / `.trim` on it would throw, and this middleware is
152
+ // contractually not allowed to turn a bad request into a 500.
153
+ const header = (name) => {
154
+ const value = req.headers?.[name];
155
+ return typeof value === 'string' ? value : null;
156
+ };
157
+ const auth = header('authorization');
158
+ if (auth && BEARER_SCHEME.test(auth)) {
159
+ return auth.replace(BEARER_SCHEME, '').trim() || null;
160
+ }
161
+ return header(this.HeaderName.toLowerCase())?.trim() || null;
162
+ }
163
+ };
164
+ exports.TokenAuthMiddleware = TokenAuthMiddleware;
165
+ __decorate([
166
+ (0, log_1.Logger)('rbac-http-token'),
167
+ __metadata("design:type", log_1.Log)
168
+ ], TokenAuthMiddleware.prototype, "Log", void 0);
169
+ __decorate([
170
+ (0, configuration_1.Config)('rbac.token.headerName', { defaultValue: 'x-api-key' }),
171
+ __metadata("design:type", String)
172
+ ], TokenAuthMiddleware.prototype, "HeaderName", void 0);
173
+ __decorate([
174
+ (0, configuration_1.Config)('rbac.token.lastUsedUpdateInterval', { defaultValue: 60 }),
175
+ __metadata("design:type", Number)
176
+ ], TokenAuthMiddleware.prototype, "LastUsedUpdateInterval", void 0);
177
+ exports.TokenAuthMiddleware = TokenAuthMiddleware = __decorate([
178
+ (0, di_1.Injectable)(http_1.ServerMiddleware),
179
+ __metadata("design:paramtypes", [])
180
+ ], TokenAuthMiddleware);
181
+ //# sourceMappingURL=middlewares.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/middlewares.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { OrmMigration, OrmDriver } from '@spinajs/orm';
2
+ export declare class RbacHttpTokenInitial_2026_08_11_01_00_00 extends OrmMigration {
3
+ up(connection: OrmDriver): Promise<void>;
4
+ down(_connection: OrmDriver): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RbacHttpTokenInitial_2026_08_11_01_00_00.d.ts","sourceRoot":"","sources":["../../../src/migrations/RbacHttpTokenInitial_2026_08_11_01_00_00.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAa,MAAM,cAAc,CAAC;AAElE,qBACa,wCAAyC,SAAQ,YAAY;IAC3D,EAAE,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBpD;IAGY,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAG;CAC5D"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RbacHttpTokenInitial_2026_08_11_01_00_00 = void 0;
10
+ /* eslint-disable @typescript-eslint/no-unused-vars */
11
+ const orm_1 = require("@spinajs/orm");
12
+ let RbacHttpTokenInitial_2026_08_11_01_00_00 = class RbacHttpTokenInitial_2026_08_11_01_00_00 extends orm_1.OrmMigration {
13
+ async up(connection) {
14
+ await connection.schema().createTable('rbac_access_tokens', (table) => {
15
+ table.int('Id').primaryKey().autoIncrement();
16
+ table.string('Uuid', 36).notNull();
17
+ table.string('Name', 128).notNull();
18
+ table.string('Token', 64).notNull();
19
+ table.string('Roles', 512).notNull();
20
+ table.dateTime('ExpiresAt');
21
+ table.dateTime('CreatedAt').notNull().default().dateTime();
22
+ table.dateTime('LastUsedAt');
23
+ table.int('user_id').notNull();
24
+ table.foreignKey('user_id').references('users', 'Id').cascade();
25
+ });
26
+ await connection.index().unique().table('rbac_access_tokens').name('access_token_hash_idx').columns(['Token']);
27
+ await connection.index().unique().table('rbac_access_tokens').name('access_token_uuid_idx').columns(['Uuid']);
28
+ await connection.index().table('rbac_access_tokens').name('access_token_user_idx').columns(['user_id']);
29
+ await connection.index().table('rbac_access_tokens').name('access_token_expires_idx').columns(['ExpiresAt']);
30
+ }
31
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
32
+ async down(_connection) { }
33
+ };
34
+ exports.RbacHttpTokenInitial_2026_08_11_01_00_00 = RbacHttpTokenInitial_2026_08_11_01_00_00;
35
+ exports.RbacHttpTokenInitial_2026_08_11_01_00_00 = RbacHttpTokenInitial_2026_08_11_01_00_00 = __decorate([
36
+ (0, orm_1.Migration)('default')
37
+ ], RbacHttpTokenInitial_2026_08_11_01_00_00);
38
+ //# 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,sCAAkE;AAG3D,IAAM,wCAAwC,GAA9C,MAAM,wCAAyC,SAAQ,kBAAY;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;;mDAvBY,wCAAwC;IADpD,IAAA,eAAS,EAAC,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"}