@solidxai/core 0.1.13-beta.8 → 0.1.13

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 (260) hide show
  1. package/CHANGELOG.md +8568 -0
  2. package/README.md +19 -0
  3. package/dist/commands/run-tests.command.d.ts +2 -0
  4. package/dist/commands/run-tests.command.d.ts.map +1 -1
  5. package/dist/commands/run-tests.command.js +20 -3
  6. package/dist/commands/run-tests.command.js.map +1 -1
  7. package/dist/config/cache.options.d.ts.map +1 -1
  8. package/dist/config/cache.options.js +2 -2
  9. package/dist/config/cache.options.js.map +1 -1
  10. package/dist/constants/error-messages.d.ts +7 -0
  11. package/dist/constants/error-messages.d.ts.map +1 -1
  12. package/dist/constants/error-messages.js +7 -0
  13. package/dist/constants/error-messages.js.map +1 -1
  14. package/dist/constants/media-file-types.d.ts +3 -0
  15. package/dist/constants/media-file-types.d.ts.map +1 -1
  16. package/dist/constants/media-file-types.js +47 -8
  17. package/dist/constants/media-file-types.js.map +1 -1
  18. package/dist/constants/success-messages.d.ts +3 -0
  19. package/dist/constants/success-messages.d.ts.map +1 -1
  20. package/dist/constants/success-messages.js +3 -0
  21. package/dist/constants/success-messages.js.map +1 -1
  22. package/dist/controllers/authentication.controller.d.ts +1 -1
  23. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  24. package/dist/controllers/authentication.controller.js +4 -3
  25. package/dist/controllers/authentication.controller.js.map +1 -1
  26. package/dist/controllers/field-metadata.controller.d.ts +2 -2
  27. package/dist/controllers/mpin-authentication.controller.d.ts +44 -0
  28. package/dist/controllers/mpin-authentication.controller.d.ts.map +1 -0
  29. package/dist/controllers/mpin-authentication.controller.js +102 -0
  30. package/dist/controllers/mpin-authentication.controller.js.map +1 -0
  31. package/dist/dtos/change-mpin.dto.d.ts +6 -0
  32. package/dist/dtos/change-mpin.dto.d.ts.map +1 -0
  33. package/dist/dtos/change-mpin.dto.js +39 -0
  34. package/dist/dtos/change-mpin.dto.js.map +1 -0
  35. package/dist/dtos/create-field-metadata.dto.d.ts +3 -6
  36. package/dist/dtos/create-field-metadata.dto.d.ts.map +1 -1
  37. package/dist/dtos/create-field-metadata.dto.js +15 -10
  38. package/dist/dtos/create-field-metadata.dto.js.map +1 -1
  39. package/dist/dtos/create-model-sequence.dto.d.ts +1 -1
  40. package/dist/dtos/create-model-sequence.dto.d.ts.map +1 -1
  41. package/dist/dtos/create-model-sequence.dto.js +1 -1
  42. package/dist/dtos/create-model-sequence.dto.js.map +1 -1
  43. package/dist/dtos/mpin-login.dto.d.ts +5 -0
  44. package/dist/dtos/mpin-login.dto.d.ts.map +1 -0
  45. package/dist/dtos/mpin-login.dto.js +33 -0
  46. package/dist/dtos/mpin-login.dto.js.map +1 -0
  47. package/dist/dtos/setup-mpin.dto.d.ts +7 -0
  48. package/dist/dtos/setup-mpin.dto.d.ts.map +1 -0
  49. package/dist/dtos/setup-mpin.dto.js +47 -0
  50. package/dist/dtos/setup-mpin.dto.js.map +1 -0
  51. package/dist/entities/common.entity.d.ts +4 -4
  52. package/dist/entities/common.entity.d.ts.map +1 -1
  53. package/dist/entities/common.entity.js +1 -1
  54. package/dist/entities/common.entity.js.map +1 -1
  55. package/dist/entities/dashboard-user-layout.entity.js +2 -2
  56. package/dist/entities/dashboard-user-layout.entity.js.map +1 -1
  57. package/dist/entities/field-metadata.entity.d.ts +1 -0
  58. package/dist/entities/field-metadata.entity.d.ts.map +1 -1
  59. package/dist/entities/field-metadata.entity.js +5 -1
  60. package/dist/entities/field-metadata.entity.js.map +1 -1
  61. package/dist/entities/user-device-credential.entity.d.ts +18 -0
  62. package/dist/entities/user-device-credential.entity.d.ts.map +1 -0
  63. package/dist/entities/user-device-credential.entity.js +91 -0
  64. package/dist/entities/user-device-credential.entity.js.map +1 -0
  65. package/dist/entities/user.entity.js +2 -2
  66. package/dist/entities/user.entity.js.map +1 -1
  67. package/dist/entities/view-metadata.entity.js.map +1 -1
  68. package/dist/entities/workflow-execution-artifact.entity.d.ts.map +1 -1
  69. package/dist/entities/workflow-execution-artifact.entity.js +4 -3
  70. package/dist/entities/workflow-execution-artifact.entity.js.map +1 -1
  71. package/dist/entities/workflow-execution-log.entity.d.ts.map +1 -1
  72. package/dist/entities/workflow-execution-log.entity.js +4 -3
  73. package/dist/entities/workflow-execution-log.entity.js.map +1 -1
  74. package/dist/entities/workflow-execution.entity.d.ts.map +1 -1
  75. package/dist/entities/workflow-execution.entity.js +3 -2
  76. package/dist/entities/workflow-execution.entity.js.map +1 -1
  77. package/dist/entities/workflow-secret.entity.d.ts.map +1 -1
  78. package/dist/entities/workflow-secret.entity.js +3 -2
  79. package/dist/entities/workflow-secret.entity.js.map +1 -1
  80. package/dist/entities/workflow-step-execution.entity.d.ts.map +1 -1
  81. package/dist/entities/workflow-step-execution.entity.js +3 -2
  82. package/dist/entities/workflow-step-execution.entity.js.map +1 -1
  83. package/dist/entities/workflow-trigger-execution.entity.d.ts.map +1 -1
  84. package/dist/entities/workflow-trigger-execution.entity.js +6 -5
  85. package/dist/entities/workflow-trigger-execution.entity.js.map +1 -1
  86. package/dist/filters/http-exception.filter.d.ts.map +1 -1
  87. package/dist/filters/http-exception.filter.js +5 -1
  88. package/dist/filters/http-exception.filter.js.map +1 -1
  89. package/dist/helpers/bootstrap.helper.d.ts +5 -2
  90. package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
  91. package/dist/helpers/bootstrap.helper.js +7 -3
  92. package/dist/helpers/bootstrap.helper.js.map +1 -1
  93. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +6 -0
  94. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
  95. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +54 -27
  96. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
  97. package/dist/helpers/file-download.helper.d.ts.map +1 -1
  98. package/dist/helpers/file-download.helper.js +6 -1
  99. package/dist/helpers/file-download.helper.js.map +1 -1
  100. package/dist/helpers/security.helper.d.ts +5 -1
  101. package/dist/helpers/security.helper.d.ts.map +1 -1
  102. package/dist/helpers/security.helper.js +15 -4
  103. package/dist/helpers/security.helper.js.map +1 -1
  104. package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
  105. package/dist/helpers/solid-core-error-codes-provider.service.js +45 -0
  106. package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
  107. package/dist/helpers/solid-microservice-adapter.service.d.ts.map +1 -1
  108. package/dist/helpers/solid-microservice-adapter.service.js +1 -1
  109. package/dist/helpers/solid-microservice-adapter.service.js.map +1 -1
  110. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  111. package/dist/helpers/typeorm-db-helper.js +9 -0
  112. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  113. package/dist/index.d.ts +6 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +6 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/interfaces/active-user-data.interface.d.ts +1 -0
  118. package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
  119. package/dist/interfaces/active-user-data.interface.js.map +1 -1
  120. package/dist/repository/user-device-credential.repository.d.ts +12 -0
  121. package/dist/repository/user-device-credential.repository.d.ts.map +1 -0
  122. package/dist/repository/user-device-credential.repository.js +34 -0
  123. package/dist/repository/user-device-credential.repository.js.map +1 -0
  124. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  125. package/dist/seeders/module-metadata-seeder.service.js +7 -3
  126. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  127. package/dist/seeders/seed-data/solid-core-metadata.json +168 -2
  128. package/dist/services/api-key.service.d.ts.map +1 -1
  129. package/dist/services/api-key.service.js +1 -1
  130. package/dist/services/api-key.service.js.map +1 -1
  131. package/dist/services/authentication.service.d.ts +5 -4
  132. package/dist/services/authentication.service.d.ts.map +1 -1
  133. package/dist/services/authentication.service.js +50 -19
  134. package/dist/services/authentication.service.js.map +1 -1
  135. package/dist/services/chatter-message.service.d.ts +5 -1
  136. package/dist/services/chatter-message.service.d.ts.map +1 -1
  137. package/dist/services/chatter-message.service.js +48 -13
  138. package/dist/services/chatter-message.service.js.map +1 -1
  139. package/dist/services/crud-helper.service.d.ts +1 -2
  140. package/dist/services/crud-helper.service.d.ts.map +1 -1
  141. package/dist/services/crud-helper.service.js +2 -16
  142. package/dist/services/crud-helper.service.js.map +1 -1
  143. package/dist/services/crud.service.d.ts.map +1 -1
  144. package/dist/services/crud.service.js +2 -1
  145. package/dist/services/crud.service.js.map +1 -1
  146. package/dist/services/draft-publish-helper.service.d.ts +1 -0
  147. package/dist/services/draft-publish-helper.service.d.ts.map +1 -1
  148. package/dist/services/draft-publish-helper.service.js +38 -4
  149. package/dist/services/draft-publish-helper.service.js.map +1 -1
  150. package/dist/services/field-metadata.service.d.ts +2 -2
  151. package/dist/services/field-metadata.service.d.ts.map +1 -1
  152. package/dist/services/field-metadata.service.js +4 -1
  153. package/dist/services/field-metadata.service.js.map +1 -1
  154. package/dist/services/media-storage.utils.d.ts +1 -0
  155. package/dist/services/media-storage.utils.d.ts.map +1 -1
  156. package/dist/services/media-storage.utils.js +12 -1
  157. package/dist/services/media-storage.utils.js.map +1 -1
  158. package/dist/services/media.service.d.ts.map +1 -1
  159. package/dist/services/media.service.js +1 -0
  160. package/dist/services/media.service.js.map +1 -1
  161. package/dist/services/module-metadata.service.d.ts.map +1 -1
  162. package/dist/services/module-metadata.service.js +9 -1
  163. package/dist/services/module-metadata.service.js.map +1 -1
  164. package/dist/services/mpin.service.d.ts +67 -0
  165. package/dist/services/mpin.service.d.ts.map +1 -0
  166. package/dist/services/mpin.service.js +282 -0
  167. package/dist/services/mpin.service.js.map +1 -0
  168. package/dist/services/refresh-token-ids-storage.service.d.ts +25 -6
  169. package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
  170. package/dist/services/refresh-token-ids-storage.service.js +80 -42
  171. package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
  172. package/dist/services/setting.service.d.ts.map +1 -1
  173. package/dist/services/setting.service.js +6 -1
  174. package/dist/services/setting.service.js.map +1 -1
  175. package/dist/services/settings/default-settings-provider.service.d.ts +206 -10
  176. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  177. package/dist/services/settings/default-settings-provider.service.js +120 -5
  178. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  179. package/dist/solid-core.module.d.ts +1 -3
  180. package/dist/solid-core.module.d.ts.map +1 -1
  181. package/dist/solid-core.module.js +14 -39
  182. package/dist/solid-core.module.js.map +1 -1
  183. package/dist/testing/reporter/console-reporter.d.ts +3 -0
  184. package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
  185. package/dist/testing/reporter/console-reporter.js +2 -0
  186. package/dist/testing/reporter/console-reporter.js.map +1 -1
  187. package/dist/testing/reporter/progress-reporter.d.ts +64 -0
  188. package/dist/testing/reporter/progress-reporter.d.ts.map +1 -0
  189. package/dist/testing/reporter/progress-reporter.js +224 -0
  190. package/dist/testing/reporter/progress-reporter.js.map +1 -0
  191. package/dist/testing/reporter/reporter.types.d.ts +3 -0
  192. package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
  193. package/dist/testing/reporter/reporter.types.js.map +1 -1
  194. package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
  195. package/dist/testing/runner/run-from-metadata.js +1 -0
  196. package/dist/testing/runner/run-from-metadata.js.map +1 -1
  197. package/dist/theme/theme-registry.d.ts +14 -0
  198. package/dist/theme/theme-registry.d.ts.map +1 -0
  199. package/dist/theme/theme-registry.js +147 -0
  200. package/dist/theme/theme-registry.js.map +1 -0
  201. package/package.json +2 -2
  202. package/src/commands/run-tests.command.ts +17 -3
  203. package/src/config/cache.options.ts +9 -1
  204. package/src/constants/error-messages.ts +14 -0
  205. package/src/constants/media-file-types.ts +87 -9
  206. package/src/constants/success-messages.ts +5 -0
  207. package/src/controllers/authentication.controller.ts +5 -2
  208. package/src/controllers/mpin-authentication.controller.ts +67 -0
  209. package/src/dtos/change-mpin.dto.ts +18 -0
  210. package/src/dtos/create-field-metadata.dto.ts +17 -9
  211. package/src/dtos/create-model-sequence.dto.ts +1 -1
  212. package/src/dtos/mpin-login.dto.ts +24 -0
  213. package/src/dtos/setup-mpin.dto.ts +51 -0
  214. package/src/entities/common.entity.ts +8 -4
  215. package/src/entities/dashboard-user-layout.entity.ts +2 -2
  216. package/src/entities/field-metadata.entity.ts +3 -0
  217. package/src/entities/user-device-credential.entity.ts +130 -0
  218. package/src/entities/user.entity.ts +2 -2
  219. package/src/entities/view-metadata.entity.ts +2 -2
  220. package/src/entities/workflow-execution-artifact.entity.ts +4 -3
  221. package/src/entities/workflow-execution-log.entity.ts +4 -3
  222. package/src/entities/workflow-execution.entity.ts +3 -2
  223. package/src/entities/workflow-secret.entity.ts +3 -2
  224. package/src/entities/workflow-step-execution.entity.ts +3 -2
  225. package/src/entities/workflow-trigger-execution.entity.ts +6 -5
  226. package/src/filters/http-exception.filter.ts +11 -1
  227. package/src/helpers/bootstrap.helper.ts +43 -6
  228. package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +73 -34
  229. package/src/helpers/file-download.helper.ts +15 -1
  230. package/src/helpers/security.helper.ts +35 -8
  231. package/src/helpers/solid-core-error-codes-provider.service.ts +53 -0
  232. package/src/helpers/solid-microservice-adapter.service.ts +6 -1
  233. package/src/helpers/typeorm-db-helper.ts +12 -1
  234. package/src/index.ts +6 -0
  235. package/src/interfaces/active-user-data.interface.ts +9 -0
  236. package/src/repository/user-device-credential.repository.ts +17 -0
  237. package/src/seeders/module-metadata-seeder.service.ts +11 -3
  238. package/src/seeders/seed-data/solid-core-metadata.json +168 -2
  239. package/src/services/api-key.service.ts +13 -1
  240. package/src/services/authentication.service.ts +127 -36
  241. package/src/services/chatter-message.service.ts +78 -15
  242. package/src/services/crud-helper.service.ts +19 -16
  243. package/src/services/crud.service.ts +3 -1
  244. package/src/services/draft-publish-helper.service.ts +56 -4
  245. package/src/services/field-metadata.service.ts +5 -2
  246. package/src/services/media-storage.utils.ts +26 -1
  247. package/src/services/media.service.ts +1 -0
  248. package/src/services/module-metadata.service.ts +10 -1
  249. package/src/services/mpin.service.ts +447 -0
  250. package/src/services/refresh-token-ids-storage.service.ts +229 -90
  251. package/src/services/setting.service.ts +8 -1
  252. package/src/services/settings/default-settings-provider.service.ts +131 -5
  253. package/src/solid-core.module.ts +26 -12
  254. package/src/testing/README.md +11 -1
  255. package/src/testing/reporter/console-reporter.ts +4 -0
  256. package/src/testing/reporter/progress-reporter.ts +251 -0
  257. package/src/testing/reporter/reporter.types.ts +3 -0
  258. package/src/testing/runner/run-from-metadata.ts +1 -0
  259. package/src/theme/theme-registry.ts +181 -0
  260. package/CLAUDE.md +0 -26
@@ -2360,6 +2360,164 @@
2360
2360
  }
2361
2361
  ]
2362
2362
  },
2363
+ {
2364
+ "singularName": "userDeviceCredential",
2365
+ "tableName": "ss_user_device_credential",
2366
+ "pluralName": "userDeviceCredentials",
2367
+ "displayName": "User Device Credential",
2368
+ "description": "Per-device MPIN credentials",
2369
+ "dataSource": "default",
2370
+ "dataSourceType": "postgres",
2371
+ "userKeyFieldUserKey": "credentialKey",
2372
+ "isSystem": true,
2373
+ "fields": [
2374
+ {
2375
+ "name": "credentialKey",
2376
+ "displayName": "Credential Key",
2377
+ "description": "Natural key: <username>-<deviceId>. Populated by MpinService, not by the computed-field pipeline.",
2378
+ "type": "shortText",
2379
+ "length": 512,
2380
+ "required": true,
2381
+ "unique": true,
2382
+ "index": true,
2383
+ "private": false,
2384
+ "encrypt": false,
2385
+ "isUserKey": true,
2386
+ "isSystem": true
2387
+ },
2388
+ {
2389
+ "name": "hashedCredentialRef",
2390
+ "displayName": "Hashed Credential Ref",
2391
+ "type": "shortText",
2392
+ "length": 512,
2393
+ "required": true,
2394
+ "unique": true,
2395
+ "index": true,
2396
+ "private": true,
2397
+ "encrypt": false,
2398
+ "isSystem": true
2399
+ },
2400
+ {
2401
+ "name": "hashedMpin",
2402
+ "displayName": "Hashed MPIN",
2403
+ "type": "shortText",
2404
+ "length": 512,
2405
+ "required": true,
2406
+ "unique": false,
2407
+ "index": false,
2408
+ "private": true,
2409
+ "encrypt": false,
2410
+ "isSystem": true
2411
+ },
2412
+ {
2413
+ "name": "mpinScheme",
2414
+ "displayName": "MPIN Scheme",
2415
+ "type": "selectionStatic",
2416
+ "required": true,
2417
+ "private": false,
2418
+ "encrypt": false,
2419
+ "isSystem": true,
2420
+ "selectionStaticValues": [
2421
+ "bcrypt:bcrypt"
2422
+ ]
2423
+ },
2424
+ {
2425
+ "name": "mpinSchemeVersion",
2426
+ "displayName": "MPIN Scheme Version",
2427
+ "type": "int",
2428
+ "required": true,
2429
+ "private": false,
2430
+ "encrypt": false,
2431
+ "defaultValue": "1",
2432
+ "isSystem": true
2433
+ },
2434
+ {
2435
+ "name": "deviceId",
2436
+ "displayName": "Device Id",
2437
+ "type": "shortText",
2438
+ "length": 512,
2439
+ "required": true,
2440
+ "unique": false,
2441
+ "index": true,
2442
+ "private": false,
2443
+ "encrypt": false,
2444
+ "isSystem": true
2445
+ },
2446
+ {
2447
+ "name": "deviceName",
2448
+ "displayName": "Device Name",
2449
+ "type": "shortText",
2450
+ "length": 512,
2451
+ "required": false,
2452
+ "unique": false,
2453
+ "index": false,
2454
+ "private": false,
2455
+ "encrypt": false,
2456
+ "isSystem": true
2457
+ },
2458
+ {
2459
+ "name": "platform",
2460
+ "displayName": "Platform",
2461
+ "type": "shortText",
2462
+ "length": 512,
2463
+ "required": false,
2464
+ "unique": false,
2465
+ "index": false,
2466
+ "private": false,
2467
+ "encrypt": false,
2468
+ "isSystem": true
2469
+ },
2470
+ {
2471
+ "name": "isActive",
2472
+ "displayName": "Is Active",
2473
+ "type": "boolean",
2474
+ "required": true,
2475
+ "unique": false,
2476
+ "index": false,
2477
+ "private": false,
2478
+ "encrypt": false,
2479
+ "defaultValue": "true",
2480
+ "isSystem": true
2481
+ },
2482
+ {
2483
+ "name": "failedAttempts",
2484
+ "displayName": "Failed Attempts",
2485
+ "type": "int",
2486
+ "required": true,
2487
+ "private": false,
2488
+ "encrypt": false,
2489
+ "defaultValue": "0",
2490
+ "isSystem": true
2491
+ },
2492
+ {
2493
+ "name": "lockedUntil",
2494
+ "displayName": "Locked Until",
2495
+ "type": "datetime",
2496
+ "required": false,
2497
+ "private": false,
2498
+ "encrypt": false,
2499
+ "isSystem": true
2500
+ },
2501
+ {
2502
+ "name": "lastUsedAt",
2503
+ "displayName": "Last Used At",
2504
+ "type": "datetime",
2505
+ "required": false,
2506
+ "private": false,
2507
+ "encrypt": false,
2508
+ "isSystem": true
2509
+ },
2510
+ {
2511
+ "name": "user",
2512
+ "displayName": "User",
2513
+ "type": "relation",
2514
+ "required": true,
2515
+ "private": false,
2516
+ "encrypt": false,
2517
+ "isSystem": true
2518
+ }
2519
+ ]
2520
+ },
2363
2521
  {
2364
2522
  "singularName": "userActivityHistory",
2365
2523
  "tableName": "ss_user_activity_history",
@@ -11642,7 +11800,8 @@
11642
11800
  "type": "field",
11643
11801
  "attrs": {
11644
11802
  "name": "fileSize",
11645
- "sortable": true
11803
+ "sortable": true,
11804
+ "viewWidget": "MediaFileSizeListWidget"
11646
11805
  }
11647
11806
  }
11648
11807
  ]
@@ -11807,6 +11966,13 @@
11807
11966
  "attrs": {
11808
11967
  "name": "fieldMetadata"
11809
11968
  }
11969
+ },
11970
+ {
11971
+ "type": "field",
11972
+ "attrs": {
11973
+ "name": "fileSize",
11974
+ "viewWidget": "MediaFileSizeFormViewWidget"
11975
+ }
11810
11976
  }
11811
11977
  ]
11812
11978
  }
@@ -12583,7 +12749,7 @@
12583
12749
  50
12584
12750
  ],
12585
12751
  "enableGlobalSearch": true,
12586
- "create": true,
12752
+ "create": false,
12587
12753
  "edit": true,
12588
12754
  "delete": true,
12589
12755
  "import": true,
@@ -1 +1 @@
1
- {"version":3,"file":"api-key.service.d.ts","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,qBACa,aAAa;IAIlB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGpC,gBAAgB,EAAE,oBAAoB,EACtC,yBAAyB,EAAE,yBAAyB,EACpD,qBAAqB,EAAE,qBAAqB,EAC5C,cAAc,EAAE,cAAc;IAG7C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IA+B/F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCjD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E,QAAQ,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;IAoC7B,OAAO,CAAC,IAAI;CAGf"}
1
+ {"version":3,"file":"api-key.service.d.ts","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,qBACa,aAAa;IAIlB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGpC,gBAAgB,EAAE,oBAAoB,EACtC,yBAAyB,EAAE,yBAAyB,EACpD,qBAAqB,EAAE,qBAAqB,EAC5C,cAAc,EAAE,cAAc;IAG7C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IA+B/F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCjD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E,QAAQ,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;IAgD7B,OAAO,CAAC,IAAI;CAGf"}
@@ -106,7 +106,7 @@ let ApiKeyService = ApiKeyService_1 = class ApiKeyService {
106
106
  throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.INVALID_CREDENTIALS);
107
107
  }
108
108
  const user = apiKeyRecord.user;
109
- const tokens = await this.authenticationService.generateTokens(user);
109
+ const tokens = await this.authenticationService.generateTokens(user, `apikey-${apiKeyRecord.id}`);
110
110
  return {
111
111
  user: {
112
112
  email: user.email,
@@ -1 +1 @@
1
- {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ForbiddenException,\n Injectable,\n Logger,\n NotFoundException,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { createHash, randomBytes } from 'crypto';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { CreateApiKeyDto } from 'src/dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from 'src/dtos/update-api-key.dto';\nimport { UserApiKey } from 'src/entities/user-api-key.entity';\nimport { User } from 'src/entities/user.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { UserApiKeyRepository } from 'src/repository/user-api-key.repository';\nimport { PermissionMetadataService } from 'src/services/permission-metadata.service';\nimport { AuthenticationService } from './authentication.service';\nimport { UserRepository } from 'src/repository/user.repository';\n\n@Injectable()\nexport class ApiKeyService {\n private readonly logger = new Logger(ApiKeyService.name);\n\n constructor(\n private readonly apiKeyRepository: UserApiKeyRepository,\n private readonly permissionMetadataService: PermissionMetadataService,\n private readonly authenticationService: AuthenticationService,\n private readonly userRepository: UserRepository,\n ) { }\n\n async generate(userId: number, dto: CreateApiKeyDto): Promise<{ apiKey: string; record: UserApiKey }> {\n const user = await this.apiKeyRepository.manager.findOne(User, {\n where: { id: userId },\n select: ['id', 'isAllowedToGenerateApiKeys'],\n });\n\n if (!user?.isAllowedToGenerateApiKeys) {\n throw new ForbiddenException('You are not allowed to generate API keys');\n }\n\n const rawKey = 'sldx_' + randomBytes(32).toString('hex');\n const hashedKey = this.hash(rawKey);\n const maskedKey = 'sldx_****' + rawKey.slice(-4);\n\n const record = this.apiKeyRepository.create({\n name: dto.name,\n hashedKey,\n maskedKey,\n isActive: true,\n expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,\n user,\n });\n\n await this.apiKeyRepository.save(record);\n\n // Strip hashedKey from the returned record — maskedKey is all the UI needs\n delete (record as any).hashedKey;\n\n return { apiKey: rawKey, record };\n }\n\n async validate(rawKey: string): Promise<ActiveUserData> {\n const hashedKey = this.hash(rawKey);\n\n // Bypass security rules for auth validation — must find the key regardless of caller context\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { hashedKey, isActive: true },\n relations: ['user', 'user.roles'],\n });\n\n if (!keyRecord) {\n throw new UnauthorizedException();\n }\n\n if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {\n throw new UnauthorizedException('API key expired');\n }\n\n // Fire-and-forget — does not need security rule context\n this.apiKeyRepository.update(keyRecord.id, { lastUsedAt: new Date() }).catch((err) => {\n this.logger.warn(`Failed to update lastUsedAt for key ${keyRecord.id}: ${err.message}`);\n });\n\n const roles = (keyRecord.user.roles ?? []).map((r) => r.name);\n const permissions = await this.permissionMetadataService.findAllUsingRoles(roles);\n\n return {\n sub: keyRecord.user.id,\n username: keyRecord.user.username,\n email: keyRecord.user.email,\n roles,\n permissions: permissions.map((p) => p.name),\n };\n }\n\n async updateKey(id: number, userId: number, dto: UpdateApiKeyDto): Promise<void> {\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { id, user: { id: userId } },\n });\n\n if (!keyRecord) {\n throw new NotFoundException('API key not found');\n }\n\n await this.apiKeyRepository.manager\n .createQueryBuilder()\n .update(UserApiKey)\n .set({ isActive: dto.isActive })\n .where('id = :id', { id })\n .execute();\n }\n\n\n async apiKeyMe(apiKey: string) {\n\n const hasedKey = this.hash(apiKey);\n const apiKeyRecord = await this.apiKeyRepository.findOne({\n where: {\n hashedKey: hasedKey,\n },\n relations: {\n user: {\n roles: true\n }\n }\n });\n\n if (!apiKeyRecord) {\n throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);\n }\n\n const user = apiKeyRecord.user;\n\n const tokens = await this.authenticationService.generateTokens(user);\n\n\n return {\n user: {\n email: user.email,\n mobile: user.mobile,\n username: user.username,\n forcePasswordChange: user.forcePasswordChange,\n id: user.id,\n roles: user.roles.map((role) => role.name)\n },\n ...tokens\n }\n }\n\n private hash(rawKey: string): string {\n return createHash('sha256').update(rawKey).digest('hex');\n }\n}\n"]}
1
+ {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAMwB;AACxB,mCAAiD;AACjD,gEAA8D;AAG9D,yEAA8D;AAC9D,yDAAgD;AAEhD,mFAA8E;AAC9E,+EAAqF;AACrF,qEAAiE;AACjE,mEAAgE;AAGzD,IAAM,aAAa,qBAAnB,MAAM,aAAa;IAGtB,YACqB,gBAAsC,EACtC,yBAAoD,EACpD,qBAA4C,EAC5C,cAA8B;QAH9B,qBAAgB,GAAhB,gBAAgB,CAAsB;QACtC,8BAAyB,GAAzB,yBAAyB,CAA2B;QACpD,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,mBAAc,GAAd,cAAc,CAAgB;QANlC,WAAM,GAAG,IAAI,eAAM,CAAC,eAAa,CAAC,IAAI,CAAC,CAAC;IAOrD,CAAC;IAEL,KAAK,CAAC,QAAQ,CAAC,MAAc,EAAE,GAAoB;QAC/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAI,EAAE;YAC3D,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE;YACrB,MAAM,EAAE,CAAC,IAAI,EAAE,4BAA4B,CAAC;SAC/C,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,EAAE,0BAA0B,EAAE,CAAC;YACpC,MAAM,IAAI,2BAAkB,CAAC,0CAA0C,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,GAAG,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjD,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YACxC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS;YACT,SAAS;YACT,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI;YACzD,IAAI;SACP,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAGzC,OAAQ,MAAc,CAAC,SAAS,CAAC;QAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAGpC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAClD,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;YACpC,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,MAAM,IAAI,8BAAqB,EAAE,CAAC;QACtC,CAAC;QAED,IAAI,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YAC1D,MAAM,IAAI,8BAAqB,CAAC,iBAAiB,CAAC,CAAC;QACvD,CAAC;QAGD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACjF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,SAAS,CAAC,EAAE,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAElF,OAAO;YACH,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE;YACtB,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,QAAQ;YACjC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK;YAC3B,KAAK;YACL,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAC9C,CAAC;IACN,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAU,EAAE,MAAc,EAAE,GAAoB;QAC5D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAClD,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;SACtC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACb,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO;aAC9B,kBAAkB,EAAE;aACpB,MAAM,CAAC,gCAAU,CAAC;aAClB,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;aAC/B,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC;aACzB,OAAO,EAAE,CAAC;IACnB,CAAC;IAGD,KAAK,CAAC,QAAQ,CAAC,MAAc;QAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YACrD,KAAK,EAAE;gBACH,SAAS,EAAE,QAAQ;aACtB;YACD,SAAS,EAAE;gBACP,IAAI,EAAE;oBACF,KAAK,EAAE,IAAI;iBACd;aACJ;SACJ,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,EAAE,CAAC;YAChB,MAAM,IAAI,8BAAqB,CAAC,+BAAc,CAAC,mBAAmB,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC;QAW/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAC1D,IAAI,EACJ,UAAU,YAAY,CAAC,EAAE,EAAE,CAC9B,CAAC;QAGF,OAAO;YACH,IAAI,EAAE;gBACF,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;gBAC7C,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;aAC7C;YACD,GAAG,MAAM;SACZ,CAAA;IACL,CAAC;IAEO,IAAI,CAAC,MAAc;QACvB,OAAO,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;CACJ,CAAA;AAhJY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAK8B,8CAAoB;QACX,uDAAyB;QAC7B,8CAAqB;QAC5B,gCAAc;GAP1C,aAAa,CAgJzB","sourcesContent":["import {\n ForbiddenException,\n Injectable,\n Logger,\n NotFoundException,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { createHash, randomBytes } from 'crypto';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { CreateApiKeyDto } from 'src/dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from 'src/dtos/update-api-key.dto';\nimport { UserApiKey } from 'src/entities/user-api-key.entity';\nimport { User } from 'src/entities/user.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { UserApiKeyRepository } from 'src/repository/user-api-key.repository';\nimport { PermissionMetadataService } from 'src/services/permission-metadata.service';\nimport { AuthenticationService } from './authentication.service';\nimport { UserRepository } from 'src/repository/user.repository';\n\n@Injectable()\nexport class ApiKeyService {\n private readonly logger = new Logger(ApiKeyService.name);\n\n constructor(\n private readonly apiKeyRepository: UserApiKeyRepository,\n private readonly permissionMetadataService: PermissionMetadataService,\n private readonly authenticationService: AuthenticationService,\n private readonly userRepository: UserRepository,\n ) { }\n\n async generate(userId: number, dto: CreateApiKeyDto): Promise<{ apiKey: string; record: UserApiKey }> {\n const user = await this.apiKeyRepository.manager.findOne(User, {\n where: { id: userId },\n select: ['id', 'isAllowedToGenerateApiKeys'],\n });\n\n if (!user?.isAllowedToGenerateApiKeys) {\n throw new ForbiddenException('You are not allowed to generate API keys');\n }\n\n const rawKey = 'sldx_' + randomBytes(32).toString('hex');\n const hashedKey = this.hash(rawKey);\n const maskedKey = 'sldx_****' + rawKey.slice(-4);\n\n const record = this.apiKeyRepository.create({\n name: dto.name,\n hashedKey,\n maskedKey,\n isActive: true,\n expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,\n user,\n });\n\n await this.apiKeyRepository.save(record);\n\n // Strip hashedKey from the returned record — maskedKey is all the UI needs\n delete (record as any).hashedKey;\n\n return { apiKey: rawKey, record };\n }\n\n async validate(rawKey: string): Promise<ActiveUserData> {\n const hashedKey = this.hash(rawKey);\n\n // Bypass security rules for auth validation — must find the key regardless of caller context\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { hashedKey, isActive: true },\n relations: ['user', 'user.roles'],\n });\n\n if (!keyRecord) {\n throw new UnauthorizedException();\n }\n\n if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {\n throw new UnauthorizedException('API key expired');\n }\n\n // Fire-and-forget — does not need security rule context\n this.apiKeyRepository.update(keyRecord.id, { lastUsedAt: new Date() }).catch((err) => {\n this.logger.warn(`Failed to update lastUsedAt for key ${keyRecord.id}: ${err.message}`);\n });\n\n const roles = (keyRecord.user.roles ?? []).map((r) => r.name);\n const permissions = await this.permissionMetadataService.findAllUsingRoles(roles);\n\n return {\n sub: keyRecord.user.id,\n username: keyRecord.user.username,\n email: keyRecord.user.email,\n roles,\n permissions: permissions.map((p) => p.name),\n };\n }\n\n async updateKey(id: number, userId: number, dto: UpdateApiKeyDto): Promise<void> {\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { id, user: { id: userId } },\n });\n\n if (!keyRecord) {\n throw new NotFoundException('API key not found');\n }\n\n await this.apiKeyRepository.manager\n .createQueryBuilder()\n .update(UserApiKey)\n .set({ isActive: dto.isActive })\n .where('id = :id', { id })\n .execute();\n }\n\n\n async apiKeyMe(apiKey: string) {\n\n const hasedKey = this.hash(apiKey);\n const apiKeyRecord = await this.apiKeyRepository.findOne({\n where: {\n hashedKey: hasedKey,\n },\n relations: {\n user: {\n roles: true\n }\n }\n });\n\n if (!apiKeyRecord) {\n throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);\n }\n\n const user = apiKeyRecord.user;\n\n // Keyed on the API key record so every call for this key reuses one\n // refresh-token bucket. Without it each call mints a fresh key and\n // therefore a new bucket with a refreshTokenTtl lifetime - a client\n // polling this endpoint would accumulate them without bound.\n //\n // The consequence is that replicas sharing one API key share one\n // bucket and invalidate each other, which is exactly the behaviour\n // before per-device sessions existed, and is benign here: an API key\n // is a permanent credential, so a failed refresh just re-mints.\n const tokens = await this.authenticationService.generateTokens(\n user,\n `apikey-${apiKeyRecord.id}`,\n );\n\n\n return {\n user: {\n email: user.email,\n mobile: user.mobile,\n username: user.username,\n forcePasswordChange: user.forcePasswordChange,\n id: user.id,\n roles: user.roles.map((role) => role.name)\n },\n ...tokens\n }\n }\n\n private hash(rawKey: string): string {\n return createHash('sha256').update(rawKey).digest('hex');\n }\n}\n"]}
@@ -160,12 +160,12 @@ export declare class AuthenticationService {
160
160
  data: {};
161
161
  }>;
162
162
  private notifyUserOnPasswordChanged;
163
- generateTokens(user: User): Promise<{
163
+ generateTokens(user: User, deviceId?: string): Promise<{
164
164
  accessToken: string;
165
165
  refreshToken: string;
166
166
  }>;
167
- generateAccessToken(user: User, sessionId?: string): Promise<string>;
168
- generateRefreshToken(user: User, previousRefreshToken?: string): Promise<string>;
167
+ generateAccessToken(user: User, sessionId?: string, deviceKey?: string): Promise<string>;
168
+ generateRefreshToken(user: User, previousRefreshToken?: string, deviceKey?: string): Promise<string>;
169
169
  refreshTokens(refreshTokenDto: RefreshTokenDto): Promise<{
170
170
  accessToken: string;
171
171
  refreshToken: string;
@@ -235,9 +235,10 @@ export declare class AuthenticationService {
235
235
  private checkAccountBlocked;
236
236
  private incrementFailedAttempts;
237
237
  private resetFailedAttempts;
238
- logout(refreshToken: string): Promise<{
238
+ logout(refreshToken: string, allDevices?: boolean): Promise<{
239
239
  message: string;
240
240
  }>;
241
+ private verifyRefreshTokenForLogout;
241
242
  activateUser(userId: number): Promise<void>;
242
243
  me(activeUser: ActiveUserData): Promise<{
243
244
  user: {
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"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"}
@@ -1101,7 +1101,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1101
1101
  }, this.settingService.getConfigValue("shouldQueueSms"));
1102
1102
  }
1103
1103
  }
1104
- async generateTokens(user) {
1104
+ async generateTokens(user, deviceId) {
1105
1105
  const sessionId = this.shouldPreventConcurrentLogins()
1106
1106
  ? (0, crypto_1.randomUUID)()
1107
1107
  : undefined;
@@ -1111,16 +1111,19 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1111
1111
  else {
1112
1112
  await this.activeSessionStorage.clearActiveSession(user.id);
1113
1113
  }
1114
+ const deviceKey = this.refreshTokenIdsStorage.areConcurrentLoginsAllowed()
1115
+ ? deviceId ?? (0, crypto_1.randomUUID)()
1116
+ : undefined;
1114
1117
  const [accessToken, refreshToken] = await Promise.all([
1115
- await this.generateAccessToken(user, sessionId),
1116
- await this.generateRefreshToken(user),
1118
+ await this.generateAccessToken(user, sessionId, deviceKey),
1119
+ await this.generateRefreshToken(user, undefined, deviceKey),
1117
1120
  ]);
1118
1121
  return {
1119
1122
  accessToken,
1120
1123
  refreshToken,
1121
1124
  };
1122
1125
  }
1123
- async generateAccessToken(user, sessionId) {
1126
+ async generateAccessToken(user, sessionId, deviceKey) {
1124
1127
  const userRoleNames = user.roles.map((role) => role.name);
1125
1128
  const resolvedSessionId = this.shouldPreventConcurrentLogins()
1126
1129
  ? sessionId ?? (await this.activeSessionStorage.getActiveSession(user.id))
@@ -1131,16 +1134,22 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1131
1134
  email: user.email,
1132
1135
  roles: userRoleNames,
1133
1136
  ...(resolvedSessionId ? { sessionId: resolvedSessionId } : {}),
1137
+ ...(deviceKey ? { deviceKey } : {}),
1134
1138
  });
1135
1139
  return accessToken;
1136
1140
  }
1137
- async generateRefreshToken(user, previousRefreshToken) {
1141
+ async generateRefreshToken(user, previousRefreshToken, deviceKey) {
1138
1142
  const refreshTokenId = (0, crypto_1.randomUUID)();
1139
1143
  const refreshTokenTtl = this.settingService.getConfigValue("refreshTokenTtl");
1144
+ const epoch = deviceKey
1145
+ ? await this.refreshTokenIdsStorage.getEpoch(user.id)
1146
+ : undefined;
1140
1147
  const refreshToken = await this.signToken(user.id, refreshTokenTtl, {
1141
1148
  refreshTokenId,
1149
+ ...(deviceKey ? { deviceKey } : {}),
1150
+ ...(epoch !== undefined ? { epoch } : {}),
1142
1151
  });
1143
- await this.refreshTokenIdsStorage.insert(user.id, refreshToken, previousRefreshToken);
1152
+ await this.refreshTokenIdsStorage.insert(user.id, refreshToken, previousRefreshToken, deviceKey);
1144
1153
  return refreshToken;
1145
1154
  }
1146
1155
  async refreshTokens(refreshTokenDto) {
@@ -1148,7 +1157,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1148
1157
  const secret = this.settingService.getConfigValue("secret");
1149
1158
  const audience = this.settingService.getConfigValue("audience");
1150
1159
  const issuer = this.settingService.getConfigValue("issuer");
1151
- const { sub } = await this.jwtService.verifyAsync(refreshTokenDto.refreshToken, {
1160
+ const { sub, deviceKey, epoch } = await this.jwtService.verifyAsync(refreshTokenDto.refreshToken, {
1152
1161
  secret,
1153
1162
  audience,
1154
1163
  issuer,
@@ -1164,11 +1173,11 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1164
1173
  if (!user) {
1165
1174
  throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.SESSION_INVALID);
1166
1175
  }
1167
- const currentRefreshToken = await this.refreshTokenIdsStorage.validateAndRotate(user, refreshTokenDto.refreshToken);
1176
+ const rotated = await this.refreshTokenIdsStorage.validateAndRotate(user, refreshTokenDto.refreshToken, { deviceKey, epoch });
1168
1177
  await this.userActivityHistoryService.logEvent("tokenRefreshed", user);
1169
1178
  return {
1170
- accessToken: await this.generateAccessToken(user),
1171
- refreshToken: currentRefreshToken,
1179
+ accessToken: await this.generateAccessToken(user, undefined, rotated.deviceKey),
1180
+ refreshToken: rotated.refreshToken,
1172
1181
  };
1173
1182
  }
1174
1183
  catch (err) {
@@ -1471,21 +1480,29 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1471
1480
  user.failedLoginAttempts = 0;
1472
1481
  await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
1473
1482
  }
1474
- async logout(refreshToken) {
1483
+ async logout(refreshToken, allDevices = false) {
1475
1484
  try {
1476
- const payload = this.jwtService.decode(refreshToken);
1477
- if (!payload || !payload.sub) {
1478
- throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.INVALID_REFRESH_TOKEN);
1485
+ const payload = await this.verifyRefreshTokenForLogout(refreshToken);
1486
+ if (!payload?.sub) {
1487
+ this.logger.warn("logout called with an unverifiable refresh token");
1488
+ return { message: success_messages_1.SUCCESS_MESSAGES.LOGOUT_SUCCESS };
1479
1489
  }
1480
1490
  const userId = payload.sub;
1481
- await this.refreshTokenIdsStorage.invalidate(userId);
1491
+ if (allDevices) {
1492
+ await this.refreshTokenIdsStorage.invalidateAll(userId);
1493
+ }
1494
+ else {
1495
+ await this.refreshTokenIdsStorage.invalidate(userId, payload.deviceKey);
1496
+ }
1482
1497
  await this.activeSessionStorage.clearActiveSession(userId);
1483
1498
  const user = await this.userRepository.findOne({
1484
1499
  where: {
1485
1500
  id: userId,
1486
1501
  },
1487
1502
  });
1488
- await this.userActivityHistoryService.logEvent("logout", user);
1503
+ if (user) {
1504
+ await this.userActivityHistoryService.logEvent("logout", user);
1505
+ }
1489
1506
  return { message: success_messages_1.SUCCESS_MESSAGES.LOGOUT_SUCCESS };
1490
1507
  }
1491
1508
  catch (err) {
@@ -1495,6 +1512,20 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1495
1512
  : new common_1.InternalServerErrorException(error_messages_1.ERROR_MESSAGES.LOGOUT_FAILED);
1496
1513
  }
1497
1514
  }
1515
+ async verifyRefreshTokenForLogout(refreshToken) {
1516
+ try {
1517
+ const payload = await this.jwtService.verifyAsync(refreshToken, {
1518
+ secret: this.settingService.getConfigValue("secret"),
1519
+ audience: this.settingService.getConfigValue("audience"),
1520
+ issuer: this.settingService.getConfigValue("issuer"),
1521
+ ignoreExpiration: true,
1522
+ });
1523
+ return payload?.refreshTokenId ? payload : null;
1524
+ }
1525
+ catch {
1526
+ return null;
1527
+ }
1528
+ }
1498
1529
  async activateUser(userId) {
1499
1530
  const user = await this.userService.findOne(userId, {});
1500
1531
  if (!user) {
@@ -1512,7 +1543,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1512
1543
  roles: true,
1513
1544
  },
1514
1545
  });
1515
- const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(user.id);
1546
+ const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(user.id, activeUser.deviceKey);
1516
1547
  const response = {
1517
1548
  user: {
1518
1549
  email: user.email,
@@ -1521,12 +1552,12 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1521
1552
  id: user.id,
1522
1553
  roles: user.roles.map((role) => role.name),
1523
1554
  },
1524
- refreshToken: refreshTokenState.currentRefreshToken,
1555
+ refreshToken: refreshTokenState?.currentRefreshToken ?? null,
1525
1556
  };
1526
1557
  return response;
1527
1558
  }
1528
1559
  async generateSsoCode(activeUser, rawAccessToken) {
1529
- const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(activeUser.sub);
1560
+ const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(activeUser.sub, activeUser.deviceKey);
1530
1561
  if (!refreshTokenState?.currentRefreshToken) {
1531
1562
  throw new common_1.UnauthorizedException("No active session found");
1532
1563
  }