@hilbras/keystone 1.6.0 → 1.9.0

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 (559) hide show
  1. package/CHANGELOG.md +239 -0
  2. package/README.md +55 -25
  3. package/dist/cli.js +25 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +15 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +45 -8
  8. package/dist/config.js.map +1 -1
  9. package/dist/container.d.ts +4 -1
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js.map +1 -1
  12. package/dist/db/migrations/0008_flashy_firestar.sql +5 -0
  13. package/dist/db/migrations/0009_daffy_changeling.sql +1 -0
  14. package/dist/db/migrations/0010_wealthy_shadow_king.sql +37 -0
  15. package/dist/db/migrations/0011_overrated_vector.sql +18 -0
  16. package/dist/db/migrations/0012_brave_darkhawk.sql +28 -0
  17. package/dist/db/migrations/0013_wonderful_chimera.sql +5 -0
  18. package/dist/db/migrations/0014_magical_morph.sql +48 -0
  19. package/{src/db/migrations/meta/0007_snapshot.json → dist/db/migrations/meta/0008_snapshot.json} +136 -32
  20. package/{src/db/migrations/meta/0006_snapshot.json → dist/db/migrations/meta/0009_snapshot.json} +359 -30
  21. package/{src/db/migrations/meta/0005_snapshot.json → dist/db/migrations/meta/0010_snapshot.json} +459 -29
  22. package/{src/db/migrations/meta/0004_snapshot.json → dist/db/migrations/meta/0011_snapshot.json} +594 -30
  23. package/dist/db/migrations/meta/0012_snapshot.json +3891 -0
  24. package/dist/db/migrations/meta/0013_snapshot.json +3919 -0
  25. package/dist/db/migrations/meta/0014_snapshot.json +4311 -0
  26. package/dist/db/migrations/meta/_journal.json +49 -0
  27. package/dist/db/reencryptOidcSecrets.d.ts +2 -0
  28. package/dist/db/reencryptOidcSecrets.d.ts.map +1 -0
  29. package/dist/db/reencryptOidcSecrets.js +41 -0
  30. package/dist/db/reencryptOidcSecrets.js.map +1 -0
  31. package/dist/db/schema.d.ts +2521 -53
  32. package/dist/db/schema.d.ts.map +1 -1
  33. package/dist/db/schema.js +118 -3
  34. package/dist/db/schema.js.map +1 -1
  35. package/dist/db/seed.js +67 -40
  36. package/dist/db/seed.js.map +1 -1
  37. package/dist/di.d.ts.map +1 -1
  38. package/dist/di.js +11 -3
  39. package/dist/di.js.map +1 -1
  40. package/dist/index.d.ts +2 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +26 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/lib/errors.d.ts +2 -1
  45. package/dist/lib/errors.d.ts.map +1 -1
  46. package/dist/lib/errors.js +10 -0
  47. package/dist/lib/errors.js.map +1 -1
  48. package/dist/plugins/appContext.d.ts.map +1 -1
  49. package/dist/plugins/appContext.js +3 -12
  50. package/dist/plugins/appContext.js.map +1 -1
  51. package/dist/plugins/audit.d.ts.map +1 -1
  52. package/dist/plugins/audit.js +26 -6
  53. package/dist/plugins/audit.js.map +1 -1
  54. package/dist/plugins/auth.d.ts.map +1 -1
  55. package/dist/plugins/auth.js +32 -7
  56. package/dist/plugins/auth.js.map +1 -1
  57. package/dist/plugins/metrics.d.ts.map +1 -1
  58. package/dist/plugins/mtls.d.ts.map +1 -1
  59. package/dist/plugins/permissions.d.ts.map +1 -1
  60. package/dist/plugins/permissions.js +29 -9
  61. package/dist/plugins/permissions.js.map +1 -1
  62. package/dist/plugins/rateLimit.d.ts +15 -0
  63. package/dist/plugins/rateLimit.d.ts.map +1 -1
  64. package/dist/plugins/rateLimit.js +11 -1
  65. package/dist/plugins/rateLimit.js.map +1 -1
  66. package/dist/plugins/requestLogger.d.ts.map +1 -1
  67. package/dist/repositories/apiKey.d.ts.map +1 -1
  68. package/dist/repositories/application.d.ts.map +1 -1
  69. package/dist/repositories/application.js +1 -1
  70. package/dist/repositories/application.js.map +1 -1
  71. package/dist/repositories/audit.d.ts.map +1 -1
  72. package/dist/repositories/index.d.ts +3 -0
  73. package/dist/repositories/index.d.ts.map +1 -1
  74. package/dist/repositories/index.js +3 -0
  75. package/dist/repositories/index.js.map +1 -1
  76. package/dist/repositories/mfaChallenge.d.ts +23 -0
  77. package/dist/repositories/mfaChallenge.d.ts.map +1 -0
  78. package/dist/repositories/mfaChallenge.js +71 -0
  79. package/dist/repositories/mfaChallenge.js.map +1 -0
  80. package/dist/repositories/oidcConnection.d.ts +27 -43
  81. package/dist/repositories/oidcConnection.d.ts.map +1 -1
  82. package/dist/repositories/oidcConnection.js +15 -6
  83. package/dist/repositories/oidcConnection.js.map +1 -1
  84. package/dist/repositories/organization.d.ts +9 -9
  85. package/dist/repositories/organization.d.ts.map +1 -1
  86. package/dist/repositories/organization.js +91 -37
  87. package/dist/repositories/organization.js.map +1 -1
  88. package/dist/repositories/permission.d.ts.map +1 -1
  89. package/dist/repositories/permission.js +27 -5
  90. package/dist/repositories/permission.js.map +1 -1
  91. package/dist/repositories/samlConnection.d.ts +28 -28
  92. package/dist/repositories/samlConnection.d.ts.map +1 -1
  93. package/dist/repositories/samlConnection.js +12 -4
  94. package/dist/repositories/samlConnection.js.map +1 -1
  95. package/dist/repositories/scimConnection.d.ts +38 -0
  96. package/dist/repositories/scimConnection.d.ts.map +1 -0
  97. package/dist/repositories/scimConnection.js +123 -0
  98. package/dist/repositories/scimConnection.js.map +1 -0
  99. package/dist/repositories/scimGroup.d.ts +36 -0
  100. package/dist/repositories/scimGroup.d.ts.map +1 -0
  101. package/dist/repositories/scimGroup.js +113 -0
  102. package/dist/repositories/scimGroup.js.map +1 -0
  103. package/dist/repositories/session.d.ts +23 -13
  104. package/dist/repositories/session.d.ts.map +1 -1
  105. package/dist/repositories/session.js +13 -1
  106. package/dist/repositories/session.js.map +1 -1
  107. package/dist/repositories/types.d.ts +112 -5
  108. package/dist/repositories/types.d.ts.map +1 -1
  109. package/dist/repositories/types.js +7 -1
  110. package/dist/repositories/types.js.map +1 -1
  111. package/dist/repositories/user.d.ts +23 -1
  112. package/dist/repositories/user.d.ts.map +1 -1
  113. package/dist/repositories/user.js +180 -4
  114. package/dist/repositories/user.js.map +1 -1
  115. package/dist/routes/admin/billing.js +4 -4
  116. package/dist/routes/admin/billing.js.map +1 -1
  117. package/dist/routes/admin/helpers.d.ts +16 -20
  118. package/dist/routes/admin/helpers.d.ts.map +1 -1
  119. package/dist/routes/admin/helpers.js +53 -10
  120. package/dist/routes/admin/helpers.js.map +1 -1
  121. package/dist/routes/admin/organizations.d.ts.map +1 -1
  122. package/dist/routes/admin/organizations.js +76 -69
  123. package/dist/routes/admin/organizations.js.map +1 -1
  124. package/dist/routes/admin/permissions.d.ts.map +1 -1
  125. package/dist/routes/admin/permissions.js +48 -14
  126. package/dist/routes/admin/permissions.js.map +1 -1
  127. package/dist/routes/admin/platform.d.ts.map +1 -1
  128. package/dist/routes/admin/platform.js +86 -35
  129. package/dist/routes/admin/platform.js.map +1 -1
  130. package/dist/routes/admin/sso.d.ts.map +1 -1
  131. package/dist/routes/admin/sso.js +143 -12
  132. package/dist/routes/admin/sso.js.map +1 -1
  133. package/dist/routes/admin/webhooks.js +8 -8
  134. package/dist/routes/admin/webhooks.js.map +1 -1
  135. package/dist/routes/apiKeys.d.ts.map +1 -1
  136. package/dist/routes/apiKeys.js +23 -5
  137. package/dist/routes/apiKeys.js.map +1 -1
  138. package/dist/routes/auth.d.ts.map +1 -1
  139. package/dist/routes/auth.js +112 -22
  140. package/dist/routes/auth.js.map +1 -1
  141. package/dist/routes/authz.d.ts.map +1 -1
  142. package/dist/routes/authz.js +16 -4
  143. package/dist/routes/authz.js.map +1 -1
  144. package/dist/routes/config.d.ts.map +1 -1
  145. package/dist/routes/config.js +16 -14
  146. package/dist/routes/config.js.map +1 -1
  147. package/dist/routes/federation.d.ts.map +1 -1
  148. package/dist/routes/federation.js +17 -3
  149. package/dist/routes/federation.js.map +1 -1
  150. package/dist/routes/magicLinks.d.ts.map +1 -1
  151. package/dist/routes/magicLinks.js +15 -3
  152. package/dist/routes/magicLinks.js.map +1 -1
  153. package/dist/routes/oauth.d.ts.map +1 -1
  154. package/dist/routes/oauth.js +22 -3
  155. package/dist/routes/oauth.js.map +1 -1
  156. package/dist/routes/oauth2.d.ts.map +1 -1
  157. package/dist/routes/oauth2.js +104 -11
  158. package/dist/routes/oauth2.js.map +1 -1
  159. package/dist/routes/oidcEnterprise.d.ts.map +1 -1
  160. package/dist/routes/oidcEnterprise.js +67 -21
  161. package/dist/routes/oidcEnterprise.js.map +1 -1
  162. package/dist/routes/password.d.ts.map +1 -1
  163. package/dist/routes/password.js.map +1 -1
  164. package/dist/routes/profile.js +4 -4
  165. package/dist/routes/profile.js.map +1 -1
  166. package/dist/routes/saml.d.ts +9 -0
  167. package/dist/routes/saml.d.ts.map +1 -1
  168. package/dist/routes/saml.js +187 -11
  169. package/dist/routes/saml.js.map +1 -1
  170. package/dist/routes/scim.d.ts +13 -0
  171. package/dist/routes/scim.d.ts.map +1 -1
  172. package/dist/routes/scim.js +885 -110
  173. package/dist/routes/scim.js.map +1 -1
  174. package/dist/routes/sdk.d.ts.map +1 -1
  175. package/dist/routes/sdk.js +24 -8
  176. package/dist/routes/sdk.js.map +1 -1
  177. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  178. package/dist/routes/serviceAccounts.js +2 -1
  179. package/dist/routes/serviceAccounts.js.map +1 -1
  180. package/dist/routes/setup.d.ts.map +1 -1
  181. package/dist/routes/setup.js +15 -16
  182. package/dist/routes/setup.js.map +1 -1
  183. package/dist/routes/smsOtp.js +1 -1
  184. package/dist/routes/smsOtp.js.map +1 -1
  185. package/dist/routes/totp.d.ts.map +1 -1
  186. package/dist/routes/totp.js +113 -23
  187. package/dist/routes/totp.js.map +1 -1
  188. package/dist/routes/webauthn.d.ts.map +1 -1
  189. package/dist/routes/webauthn.js +44 -8
  190. package/dist/routes/webauthn.js.map +1 -1
  191. package/dist/routes/workflows.d.ts.map +1 -1
  192. package/dist/routes/workflows.js +58 -25
  193. package/dist/routes/workflows.js.map +1 -1
  194. package/dist/sdk/index.d.ts.map +1 -1
  195. package/dist/sdk/index.js +141 -40
  196. package/dist/sdk/index.js.map +1 -1
  197. package/dist/sdk/types.d.ts +60 -29
  198. package/dist/sdk/types.d.ts.map +1 -1
  199. package/dist/services/application/authentication.d.ts +39 -1
  200. package/dist/services/application/authentication.d.ts.map +1 -1
  201. package/dist/services/application/authentication.js +43 -1
  202. package/dist/services/application/authentication.js.map +1 -1
  203. package/dist/services/application/identity.d.ts +10 -7
  204. package/dist/services/application/identity.d.ts.map +1 -1
  205. package/dist/services/application/identity.js +13 -10
  206. package/dist/services/application/identity.js.map +1 -1
  207. package/dist/services/application/organization.d.ts +11 -7
  208. package/dist/services/application/organization.d.ts.map +1 -1
  209. package/dist/services/application/organization.js +160 -12
  210. package/dist/services/application/organization.js.map +1 -1
  211. package/dist/services/applications.js +2 -2
  212. package/dist/services/applications.js.map +1 -1
  213. package/dist/services/audit.d.ts +1 -0
  214. package/dist/services/audit.d.ts.map +1 -1
  215. package/dist/services/audit.js +13 -0
  216. package/dist/services/audit.js.map +1 -1
  217. package/dist/services/cache.d.ts.map +1 -1
  218. package/dist/services/configuration/profiles.d.ts +4 -0
  219. package/dist/services/configuration/profiles.d.ts.map +1 -1
  220. package/dist/services/configuration/profiles.js +50 -0
  221. package/dist/services/configuration/profiles.js.map +1 -1
  222. package/dist/services/configuration.d.ts.map +1 -1
  223. package/dist/services/configuration.js.map +1 -1
  224. package/dist/services/connectors/google.d.ts.map +1 -1
  225. package/dist/services/connectors/google.js +3 -2
  226. package/dist/services/connectors/google.js.map +1 -1
  227. package/dist/services/connectors/oidc.d.ts.map +1 -1
  228. package/dist/services/connectors/oidc.js +6 -3
  229. package/dist/services/connectors/oidc.js.map +1 -1
  230. package/dist/services/connectors/zitadel.d.ts.map +1 -1
  231. package/dist/services/connectors/zitadel.js +4 -3
  232. package/dist/services/connectors/zitadel.js.map +1 -1
  233. package/dist/services/domain/authentication.d.ts +43 -4
  234. package/dist/services/domain/authentication.d.ts.map +1 -1
  235. package/dist/services/domain/authentication.js +82 -20
  236. package/dist/services/domain/authentication.js.map +1 -1
  237. package/dist/services/domain/authorization.d.ts +11 -0
  238. package/dist/services/domain/authorization.d.ts.map +1 -1
  239. package/dist/services/domain/authorization.js +36 -1
  240. package/dist/services/domain/authorization.js.map +1 -1
  241. package/dist/services/domain/identity.d.ts +21 -9
  242. package/dist/services/domain/identity.d.ts.map +1 -1
  243. package/dist/services/domain/identity.js +187 -10
  244. package/dist/services/domain/identity.js.map +1 -1
  245. package/dist/services/domain/organization.d.ts +6 -9
  246. package/dist/services/domain/organization.d.ts.map +1 -1
  247. package/dist/services/domain/organization.js +48 -30
  248. package/dist/services/domain/organization.js.map +1 -1
  249. package/dist/services/emailVerification.d.ts +2 -2
  250. package/dist/services/enterpriseSso.d.ts +13 -6
  251. package/dist/services/enterpriseSso.d.ts.map +1 -1
  252. package/dist/services/enterpriseSso.js +75 -6
  253. package/dist/services/enterpriseSso.js.map +1 -1
  254. package/dist/services/events/subscribers/auditLog.js +1 -1
  255. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  256. package/dist/services/events/types.d.ts +7 -1
  257. package/dist/services/events/types.d.ts.map +1 -1
  258. package/dist/services/events/types.js.map +1 -1
  259. package/dist/services/events/validate.d.ts.map +1 -1
  260. package/dist/services/events/validate.js +27 -0
  261. package/dist/services/events/validate.js.map +1 -1
  262. package/dist/services/features.d.ts.map +1 -1
  263. package/dist/services/features.js.map +1 -1
  264. package/dist/services/federation.d.ts +6 -1
  265. package/dist/services/federation.d.ts.map +1 -1
  266. package/dist/services/federation.js +31 -4
  267. package/dist/services/federation.js.map +1 -1
  268. package/dist/services/ipControls.js +2 -2
  269. package/dist/services/ipControls.js.map +1 -1
  270. package/dist/services/magicLinks.d.ts +2 -2
  271. package/dist/services/mfa.d.ts +53 -0
  272. package/dist/services/mfa.d.ts.map +1 -0
  273. package/dist/services/mfa.js +157 -0
  274. package/dist/services/mfa.js.map +1 -0
  275. package/dist/services/oauth2.d.ts +16 -12
  276. package/dist/services/oauth2.d.ts.map +1 -1
  277. package/dist/services/oauth2.js +22 -13
  278. package/dist/services/oauth2.js.map +1 -1
  279. package/dist/services/oidcSecretFormat.d.ts +3 -0
  280. package/dist/services/oidcSecretFormat.d.ts.map +1 -0
  281. package/dist/services/oidcSecretFormat.js +5 -0
  282. package/dist/services/oidcSecretFormat.js.map +1 -0
  283. package/dist/services/organizations.d.ts +4 -16
  284. package/dist/services/organizations.d.ts.map +1 -1
  285. package/dist/services/organizations.js +0 -62
  286. package/dist/services/organizations.js.map +1 -1
  287. package/dist/services/permissions.d.ts.map +1 -1
  288. package/dist/services/permissions.js +9 -1
  289. package/dist/services/permissions.js.map +1 -1
  290. package/dist/services/plugins/registry.d.ts.map +1 -1
  291. package/dist/services/plugins/registry.js.map +1 -1
  292. package/dist/services/plugins/types.d.ts.map +1 -1
  293. package/dist/services/queue/bullmq.d.ts.map +1 -1
  294. package/dist/services/queue/inProcess.d.ts.map +1 -1
  295. package/dist/services/redis.d.ts +1 -1
  296. package/dist/services/redis.d.ts.map +1 -1
  297. package/dist/services/scimCredentials.d.ts +46 -0
  298. package/dist/services/scimCredentials.d.ts.map +1 -0
  299. package/dist/services/scimCredentials.js +123 -0
  300. package/dist/services/scimCredentials.js.map +1 -0
  301. package/dist/services/scimLegacyMigration.d.ts +12 -0
  302. package/dist/services/scimLegacyMigration.d.ts.map +1 -0
  303. package/dist/services/scimLegacyMigration.js +44 -0
  304. package/dist/services/scimLegacyMigration.js.map +1 -0
  305. package/dist/services/secrets/awsKms.d.ts +2 -2
  306. package/dist/services/secrets/awsKms.d.ts.map +1 -1
  307. package/dist/services/secrets/awsKms.js +3 -5
  308. package/dist/services/secrets/awsKms.js.map +1 -1
  309. package/dist/services/secrets/azureKeyVault.d.ts.map +1 -1
  310. package/dist/services/secrets/database.d.ts.map +1 -1
  311. package/dist/services/secrets/database.js.map +1 -1
  312. package/dist/services/secrets/environment.d.ts.map +1 -1
  313. package/dist/services/secrets/environment.js.map +1 -1
  314. package/dist/services/secrets/index.d.ts.map +1 -1
  315. package/dist/services/secrets/password.d.ts.map +1 -1
  316. package/dist/services/secrets/password.js +0 -4
  317. package/dist/services/secrets/password.js.map +1 -1
  318. package/dist/services/secrets/provider.d.ts +2 -3
  319. package/dist/services/secrets/provider.d.ts.map +1 -1
  320. package/dist/services/secrets/vault.d.ts.map +1 -1
  321. package/dist/services/setup/configWriter.d.ts.map +1 -1
  322. package/dist/services/setup/configWriter.js.map +1 -1
  323. package/dist/services/ssoEndpointPolicy.d.ts +8 -0
  324. package/dist/services/ssoEndpointPolicy.d.ts.map +1 -0
  325. package/dist/services/ssoEndpointPolicy.js +136 -0
  326. package/dist/services/ssoEndpointPolicy.js.map +1 -0
  327. package/dist/services/stepUp.d.ts +35 -0
  328. package/dist/services/stepUp.d.ts.map +1 -0
  329. package/dist/services/stepUp.js +65 -0
  330. package/dist/services/stepUp.js.map +1 -0
  331. package/dist/services/tokens.d.ts +37 -11
  332. package/dist/services/tokens.d.ts.map +1 -1
  333. package/dist/services/tokens.js +75 -14
  334. package/dist/services/tokens.js.map +1 -1
  335. package/dist/services/totp.d.ts +46 -0
  336. package/dist/services/totp.d.ts.map +1 -1
  337. package/dist/services/totp.js +178 -41
  338. package/dist/services/totp.js.map +1 -1
  339. package/dist/services/users.d.ts +20 -12
  340. package/dist/services/users.d.ts.map +1 -1
  341. package/dist/services/users.js +24 -51
  342. package/dist/services/users.js.map +1 -1
  343. package/dist/services/webauthn.d.ts +8 -4
  344. package/dist/services/webauthn.d.ts.map +1 -1
  345. package/dist/services/webauthn.js +4 -4
  346. package/dist/services/webauthn.js.map +1 -1
  347. package/dist/services/webhooks.d.ts +20 -20
  348. package/dist/services/workflows/engine.d.ts +4 -2
  349. package/dist/services/workflows/engine.d.ts.map +1 -1
  350. package/dist/services/workflows/engine.js +181 -12
  351. package/dist/services/workflows/engine.js.map +1 -1
  352. package/dist/services/workflows/steps.d.ts +2 -0
  353. package/dist/services/workflows/steps.d.ts.map +1 -1
  354. package/dist/services/workflows/steps.js +8 -75
  355. package/dist/services/workflows/steps.js.map +1 -1
  356. package/dist/setup-server.js.map +1 -1
  357. package/dist/types.d.ts +33 -4
  358. package/dist/types.d.ts.map +1 -1
  359. package/dist/types.js +26 -2
  360. package/dist/types.js.map +1 -1
  361. package/package.json +26 -3
  362. package/dist/tests/errors.test.d.ts +0 -2
  363. package/dist/tests/errors.test.d.ts.map +0 -1
  364. package/dist/tests/errors.test.js +0 -64
  365. package/dist/tests/errors.test.js.map +0 -1
  366. package/dist/tests/events.test.d.ts +0 -2
  367. package/dist/tests/events.test.d.ts.map +0 -1
  368. package/dist/tests/events.test.js +0 -45
  369. package/dist/tests/events.test.js.map +0 -1
  370. package/dist/tests/featureFlags.test.d.ts +0 -2
  371. package/dist/tests/featureFlags.test.d.ts.map +0 -1
  372. package/dist/tests/featureFlags.test.js +0 -24
  373. package/dist/tests/featureFlags.test.js.map +0 -1
  374. package/dist/tests/integration/queue.test.d.ts +0 -2
  375. package/dist/tests/integration/queue.test.d.ts.map +0 -1
  376. package/dist/tests/integration/queue.test.js +0 -49
  377. package/dist/tests/integration/queue.test.js.map +0 -1
  378. package/dist/tests/plugins.test.d.ts +0 -2
  379. package/dist/tests/plugins.test.d.ts.map +0 -1
  380. package/dist/tests/plugins.test.js +0 -56
  381. package/dist/tests/plugins.test.js.map +0 -1
  382. package/dist/tests/result.test.d.ts +0 -2
  383. package/dist/tests/result.test.d.ts.map +0 -1
  384. package/dist/tests/result.test.js +0 -46
  385. package/dist/tests/result.test.js.map +0 -1
  386. package/dist/tests/setup/configWriter.test.d.ts +0 -2
  387. package/dist/tests/setup/configWriter.test.d.ts.map +0 -1
  388. package/dist/tests/setup/configWriter.test.js +0 -55
  389. package/dist/tests/setup/configWriter.test.js.map +0 -1
  390. package/dist/tests/setup/validation.test.d.ts +0 -2
  391. package/dist/tests/setup/validation.test.d.ts.map +0 -1
  392. package/dist/tests/setup/validation.test.js +0 -26
  393. package/dist/tests/setup/validation.test.js.map +0 -1
  394. package/dist/tests/smoke.test.d.ts +0 -2
  395. package/dist/tests/smoke.test.d.ts.map +0 -1
  396. package/dist/tests/smoke.test.js +0 -124
  397. package/dist/tests/smoke.test.js.map +0 -1
  398. package/src/cli.ts +0 -172
  399. package/src/config.ts +0 -143
  400. package/src/container.ts +0 -48
  401. package/src/db/index.ts +0 -53
  402. package/src/db/migrations/0000_skinny_ben_parker.sql +0 -553
  403. package/src/db/migrations/0001_brief_joseph.sql +0 -10
  404. package/src/db/migrations/0002_add_account_lockout.sql +0 -3
  405. package/src/db/migrations/0003_steep_rachel_grey.sql +0 -1
  406. package/src/db/migrations/0004_clever_bill_hollister.sql +0 -20
  407. package/src/db/migrations/0005_steep_the_call.sql +0 -2
  408. package/src/db/migrations/0006_ambitious_boomer.sql +0 -17
  409. package/src/db/migrations/0007_greedy_vindicator.sql +0 -40
  410. package/src/db/migrations/meta/0000_snapshot.json +0 -2964
  411. package/src/db/migrations/meta/0001_snapshot.json +0 -3031
  412. package/src/db/migrations/meta/0003_snapshot.json +0 -3051
  413. package/src/db/migrations/meta/_journal.json +0 -62
  414. package/src/db/schema.ts +0 -676
  415. package/src/db/seed.ts +0 -146
  416. package/src/di.ts +0 -81
  417. package/src/index.ts +0 -326
  418. package/src/lib/errors.ts +0 -139
  419. package/src/lib/result.ts +0 -44
  420. package/src/lib/webhookSignature.ts +0 -41
  421. package/src/plugins/appContext.ts +0 -76
  422. package/src/plugins/audit.ts +0 -42
  423. package/src/plugins/auth.ts +0 -230
  424. package/src/plugins/metrics.ts +0 -41
  425. package/src/plugins/mtls.ts +0 -94
  426. package/src/plugins/permissions.ts +0 -29
  427. package/src/plugins/rateLimit.ts +0 -133
  428. package/src/plugins/requestLogger.ts +0 -25
  429. package/src/plugins/tracing.ts +0 -22
  430. package/src/repositories/apiKey.ts +0 -158
  431. package/src/repositories/application.ts +0 -70
  432. package/src/repositories/audit.ts +0 -32
  433. package/src/repositories/index.ts +0 -9
  434. package/src/repositories/oidcConnection.ts +0 -111
  435. package/src/repositories/organization.ts +0 -167
  436. package/src/repositories/permission.ts +0 -153
  437. package/src/repositories/samlConnection.ts +0 -96
  438. package/src/repositories/session.ts +0 -86
  439. package/src/repositories/types.ts +0 -134
  440. package/src/repositories/user.ts +0 -161
  441. package/src/routes/admin/billing.ts +0 -48
  442. package/src/routes/admin/helpers.ts +0 -50
  443. package/src/routes/admin/index.ts +0 -16
  444. package/src/routes/admin/organizations.ts +0 -299
  445. package/src/routes/admin/permissions.ts +0 -80
  446. package/src/routes/admin/platform.ts +0 -335
  447. package/src/routes/admin/sso.ts +0 -138
  448. package/src/routes/admin/webhooks.ts +0 -73
  449. package/src/routes/admin.ts +0 -1
  450. package/src/routes/apiKeys.ts +0 -60
  451. package/src/routes/auth.ts +0 -214
  452. package/src/routes/authz.ts +0 -38
  453. package/src/routes/config.ts +0 -67
  454. package/src/routes/emailVerification.ts +0 -73
  455. package/src/routes/federation.ts +0 -156
  456. package/src/routes/helpers.ts +0 -17
  457. package/src/routes/magicLinks.ts +0 -107
  458. package/src/routes/oauth.ts +0 -167
  459. package/src/routes/oauth2.ts +0 -284
  460. package/src/routes/oidcEnterprise.ts +0 -166
  461. package/src/routes/password.ts +0 -90
  462. package/src/routes/profile.ts +0 -44
  463. package/src/routes/saml.ts +0 -209
  464. package/src/routes/scim.ts +0 -199
  465. package/src/routes/sdk.ts +0 -141
  466. package/src/routes/serviceAccounts.ts +0 -124
  467. package/src/routes/sessions.ts +0 -62
  468. package/src/routes/setup.ts +0 -315
  469. package/src/routes/smsOtp.ts +0 -67
  470. package/src/routes/totp.ts +0 -122
  471. package/src/routes/webauthn.ts +0 -147
  472. package/src/routes/workflows.ts +0 -157
  473. package/src/sdk/index.ts +0 -152
  474. package/src/sdk/types.ts +0 -54
  475. package/src/services/anomalyDetection.ts +0 -73
  476. package/src/services/application/authentication.ts +0 -75
  477. package/src/services/application/identity.ts +0 -56
  478. package/src/services/application/index.ts +0 -3
  479. package/src/services/application/organization.ts +0 -77
  480. package/src/services/applications.ts +0 -89
  481. package/src/services/audit.ts +0 -41
  482. package/src/services/auditExport.ts +0 -59
  483. package/src/services/billing.ts +0 -87
  484. package/src/services/cache.ts +0 -131
  485. package/src/services/configuration/profiles.ts +0 -115
  486. package/src/services/configuration.ts +0 -120
  487. package/src/services/connectors/google.ts +0 -92
  488. package/src/services/connectors/oidc.ts +0 -111
  489. package/src/services/connectors/registry.ts +0 -124
  490. package/src/services/connectors/types.ts +0 -38
  491. package/src/services/connectors/zitadel.ts +0 -77
  492. package/src/services/devices.ts +0 -76
  493. package/src/services/domain/authentication.ts +0 -279
  494. package/src/services/domain/authorization.ts +0 -49
  495. package/src/services/domain/identity.ts +0 -108
  496. package/src/services/domain/index.ts +0 -4
  497. package/src/services/domain/organization.ts +0 -114
  498. package/src/services/email.ts +0 -167
  499. package/src/services/emailVerification.ts +0 -75
  500. package/src/services/enterpriseSso.ts +0 -58
  501. package/src/services/events/bus.ts +0 -43
  502. package/src/services/events/subscribers/anomaly.ts +0 -13
  503. package/src/services/events/subscribers/auditLog.ts +0 -21
  504. package/src/services/events/subscribers/webhook.ts +0 -39
  505. package/src/services/events/subscribers/webhookDispatch.ts +0 -14
  506. package/src/services/events/types.ts +0 -106
  507. package/src/services/events/validate.ts +0 -118
  508. package/src/services/featureFlags.ts +0 -90
  509. package/src/services/features.ts +0 -22
  510. package/src/services/federation.ts +0 -30
  511. package/src/services/hibp.ts +0 -28
  512. package/src/services/ipControls.ts +0 -99
  513. package/src/services/magicLinks.ts +0 -51
  514. package/src/services/oauth2.ts +0 -216
  515. package/src/services/organizations.ts +0 -171
  516. package/src/services/permissions.ts +0 -146
  517. package/src/services/plugins/registry.ts +0 -242
  518. package/src/services/plugins/types.ts +0 -98
  519. package/src/services/queue/bullmq.ts +0 -104
  520. package/src/services/queue/inProcess.ts +0 -75
  521. package/src/services/queue/index.ts +0 -19
  522. package/src/services/queue/types.ts +0 -26
  523. package/src/services/redis.ts +0 -16
  524. package/src/services/secrets/awsKms.ts +0 -97
  525. package/src/services/secrets/azureKeyVault.ts +0 -171
  526. package/src/services/secrets/database.ts +0 -166
  527. package/src/services/secrets/environment.ts +0 -117
  528. package/src/services/secrets/index.ts +0 -50
  529. package/src/services/secrets/password.ts +0 -73
  530. package/src/services/secrets/provider.ts +0 -36
  531. package/src/services/secrets/vault.ts +0 -149
  532. package/src/services/secrets.ts +0 -2
  533. package/src/services/serviceAccounts.ts +0 -74
  534. package/src/services/setup/configWriter.ts +0 -200
  535. package/src/services/setup/diagnostics.ts +0 -76
  536. package/src/services/setup/token.ts +0 -42
  537. package/src/services/setup/types.ts +0 -40
  538. package/src/services/setup/validation.ts +0 -205
  539. package/src/services/sms.ts +0 -81
  540. package/src/services/smsOtp.ts +0 -74
  541. package/src/services/tokens.ts +0 -287
  542. package/src/services/totp.ts +0 -113
  543. package/src/services/users.ts +0 -239
  544. package/src/services/webauthn.ts +0 -193
  545. package/src/services/webhooks.ts +0 -190
  546. package/src/services/workflows/engine.ts +0 -125
  547. package/src/services/workflows/steps.ts +0 -129
  548. package/src/services/zitadel.ts +0 -277
  549. package/src/setup-server.ts +0 -71
  550. package/src/tests/errors.test.ts +0 -74
  551. package/src/tests/events.test.ts +0 -52
  552. package/src/tests/featureFlags.test.ts +0 -26
  553. package/src/tests/integration/queue.test.ts +0 -54
  554. package/src/tests/plugins.test.ts +0 -73
  555. package/src/tests/result.test.ts +0 -52
  556. package/src/tests/setup/configWriter.test.ts +0 -69
  557. package/src/tests/setup/validation.test.ts +0 -29
  558. package/src/tests/smoke.test.ts +0 -136
  559. package/src/types.ts +0 -70
@@ -1,74 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { eq, and, gt, isNull } from "drizzle-orm";
3
- import { db } from "../db/index.js";
4
- import { smsOtpCodes, users, type User } from "../db/schema.js";
5
- import { smsProvider } from "./sms.js";
6
-
7
- const CODE_TTL_SECONDS = 300;
8
- const CODE_LENGTH = 6;
9
-
10
- export function generateSmsCode(): string {
11
- return crypto.randomInt(0, 1_000_000).toString().padStart(CODE_LENGTH, "0");
12
- }
13
-
14
- function hashCode(code: string): string {
15
- return crypto.createHash("sha256").update(code).digest("hex");
16
- }
17
-
18
- export async function sendSmsOtp(user: User, phoneNumber: string): Promise<string> {
19
- const code = generateSmsCode();
20
- const expiresAt = new Date(Date.now() + CODE_TTL_SECONDS * 1000);
21
-
22
- await db.insert(smsOtpCodes).values({
23
- userId: user.id,
24
- phoneNumber,
25
- codeHash: hashCode(code),
26
- expiresAt,
27
- });
28
-
29
- await smsProvider.send({
30
- to: phoneNumber,
31
- body: `Your Hilbras verification code is: ${code}`,
32
- });
33
-
34
- return code;
35
- }
36
-
37
- export async function verifySmsOtp(userId: string, code: string): Promise<boolean> {
38
- const codeHash = hashCode(code);
39
- const now = new Date();
40
-
41
- const [record] = await db
42
- .select()
43
- .from(smsOtpCodes)
44
- .where(
45
- and(
46
- eq(smsOtpCodes.userId, userId),
47
- eq(smsOtpCodes.codeHash, codeHash),
48
- gt(smsOtpCodes.expiresAt, now),
49
- isNull(smsOtpCodes.usedAt)
50
- )
51
- )
52
- .limit(1);
53
-
54
- if (!record) return false;
55
-
56
- await db.update(smsOtpCodes).set({ usedAt: now }).where(eq(smsOtpCodes.id, record.id));
57
- return true;
58
- }
59
-
60
- export async function hasVerifiedPhone(userId: string): Promise<boolean> {
61
- const [user] = await db
62
- .select({ phoneVerified: users.phoneVerified })
63
- .from(users)
64
- .where(eq(users.id, userId))
65
- .limit(1);
66
- return user?.phoneVerified ?? false;
67
- }
68
-
69
- export async function markPhoneVerified(userId: string, phoneNumber: string): Promise<void> {
70
- await db
71
- .update(users)
72
- .set({ phoneNumber, phoneVerified: true })
73
- .where(eq(users.id, userId));
74
- }
@@ -1,287 +0,0 @@
1
- import crypto from "node:crypto";
2
- import {
3
- SignJWT,
4
- importPKCS8,
5
- importSPKI,
6
- jwtVerify,
7
- decodeProtectedHeader,
8
- exportJWK,
9
- type JWTPayload,
10
- } from "jose";
11
- import { eq, and, gt, isNull } from "drizzle-orm";
12
- import { db } from "../db/index.js";
13
- import {
14
- refreshTokens,
15
- users,
16
- type User,
17
- type RefreshToken,
18
- type Application,
19
- } from "../db/schema.js";
20
- import { config } from "../config.js";
21
- import type { TokenClaims } from "../types.js";
22
- import {
23
- getActiveSigningKey,
24
- listValidSigningKeys,
25
- type SigningKeyPair,
26
- } from "./secrets.js";
27
- import { SessionRepository } from "../repositories/session.js";
28
-
29
- /** Active signing key used to issue new tokens. */
30
- let activeKey: SigningKeyPair | null = null;
31
- /** All valid signing keys (active + grace-period keys) used for verification. */
32
- const validKeys = new Map<string, SigningKeyPair>();
33
-
34
- export async function loadSigningKeys(): Promise<void> {
35
- if (config.JWT_PRIVATE_KEY && config.JWT_PUBLIC_KEY) {
36
- const privateKey = await importPKCS8(config.JWT_PRIVATE_KEY, "RS256");
37
- const publicKey = await importSPKI(config.JWT_PUBLIC_KEY, "RS256");
38
- activeKey = { keyId: "env", privateKey, publicKey };
39
- validKeys.set(activeKey.keyId, activeKey);
40
- return;
41
- }
42
-
43
- activeKey = await getActiveSigningKey();
44
- const keys = await listValidSigningKeys();
45
- validKeys.clear();
46
- for (const key of keys) {
47
- validKeys.set(key.keyId, key);
48
- }
49
- }
50
-
51
- /**
52
- * Return the public JWK for the active signing key. Kept for backwards
53
- * compatibility; new code should prefer `getPublicJwks()`.
54
- */
55
- export async function getPublicJWK() {
56
- if (!activeKey) await loadSigningKeys();
57
- return exportJWK(activeKey!.publicKey);
58
- }
59
-
60
- /**
61
- * Return the JWKS document containing every valid public key, including
62
- * recently rotated keys still within the grace period.
63
- */
64
- export async function getPublicJwks() {
65
- if (validKeys.size === 0) await loadSigningKeys();
66
- const keys = await Promise.all(
67
- Array.from(validKeys.values()).map(async (key) => {
68
- const jwk = await exportJWK(key.publicKey);
69
- return { ...jwk, kid: key.keyId, use: "sig", key_ops: ["verify"] };
70
- })
71
- );
72
- return { keys };
73
- }
74
-
75
- function issuer(): string {
76
- return process.env.AUTH_API_PUBLIC_URL || `http://localhost:${config.PORT}`;
77
- }
78
-
79
- export interface AccessTokenOptions {
80
- appId?: string;
81
- orgId?: string;
82
- clientId?: string;
83
- deviceFingerprint?: string;
84
- }
85
-
86
- export function createAccessToken(user: User, opts: AccessTokenOptions = {}): Promise<string> {
87
- if (!activeKey) throw new Error("JWT signing keys not loaded");
88
- const claims: TokenClaims = {
89
- sub: user.id,
90
- email: user.email,
91
- username: user.username,
92
- name: user.name ?? undefined,
93
- plan: user.plan,
94
- role: user.role,
95
- provider: user.provider,
96
- };
97
- if (opts.orgId) claims.org_id = opts.orgId;
98
- if (opts.appId) claims.app_id = opts.appId;
99
- if (opts.clientId) claims.client_id = opts.clientId;
100
- if (opts.deviceFingerprint) claims.device_fingerprint = opts.deviceFingerprint;
101
- return new SignJWT(claims as unknown as Record<string, unknown>)
102
- .setProtectedHeader({ alg: "RS256", typ: "JWT", kid: activeKey.keyId })
103
- .setIssuedAt()
104
- .setIssuer(issuer())
105
- .setAudience("hilbras")
106
- .setExpirationTime(`${config.ACCESS_TOKEN_TTL_SECONDS}s`)
107
- .sign(activeKey.privateKey);
108
- }
109
-
110
- export interface ApplicationAccessTokenOptions {
111
- appId: string;
112
- orgId: string;
113
- clientId: string;
114
- scopes?: string[];
115
- }
116
-
117
- export function createApplicationAccessToken(
118
- opts: ApplicationAccessTokenOptions
119
- ): Promise<string> {
120
- if (!activeKey) throw new Error("JWT signing keys not loaded");
121
- const claims: Record<string, unknown> = {
122
- sub: opts.clientId,
123
- client_id: opts.clientId,
124
- app_id: opts.appId,
125
- org_id: opts.orgId,
126
- };
127
- if (opts.scopes && opts.scopes.length > 0) {
128
- claims.scope = opts.scopes.join(" ");
129
- }
130
- return new SignJWT(claims)
131
- .setProtectedHeader({ alg: "RS256", typ: "JWT", kid: activeKey.keyId })
132
- .setIssuedAt()
133
- .setIssuer(issuer())
134
- .setAudience("hilbras")
135
- .setExpirationTime(`${config.ACCESS_TOKEN_TTL_SECONDS}s`)
136
- .sign(activeKey.privateKey);
137
- }
138
-
139
- export async function createIdToken(
140
- user: User,
141
- app: Application,
142
- nonce?: string
143
- ): Promise<string> {
144
- if (!activeKey) throw new Error("JWT signing keys not loaded");
145
- const claims: Record<string, unknown> = {
146
- sub: user.id,
147
- email: user.email,
148
- email_verified: user.emailVerified,
149
- username: user.username,
150
- name: user.name,
151
- picture: user.avatarUrl,
152
- aud: app.clientId,
153
- azp: app.clientId,
154
- };
155
- if (nonce) claims.nonce = nonce;
156
- return new SignJWT(claims)
157
- .setProtectedHeader({ alg: "RS256", typ: "JWT", kid: activeKey.keyId })
158
- .setIssuedAt()
159
- .setIssuer(issuer())
160
- .setExpirationTime(`${config.ACCESS_TOKEN_TTL_SECONDS}s`)
161
- .sign(activeKey.privateKey);
162
- }
163
-
164
- export interface TokenSet {
165
- accessToken: string;
166
- refreshToken: string;
167
- refreshTokenHash: string;
168
- expiresAt: Date;
169
- }
170
-
171
- export async function createTokenSet(
172
- user: User,
173
- ip?: string,
174
- userAgent?: string,
175
- opts: AccessTokenOptions = {},
176
- deviceFingerprint?: string
177
- ): Promise<TokenSet> {
178
- const accessToken = await createAccessToken(user, opts);
179
- const refreshToken = crypto.randomBytes(48).toString("base64url");
180
- const refreshTokenHash = hashToken(refreshToken);
181
- const expiresAt = new Date(Date.now() + config.REFRESH_TOKEN_TTL_SECONDS * 1000);
182
-
183
- const [inserted] = await db.insert(refreshTokens).values({
184
- userId: user.id,
185
- appId: opts.appId ?? null,
186
- tokenHash: refreshTokenHash,
187
- expiresAt,
188
- ipAddress: ip ?? null,
189
- userAgent: userAgent ?? null,
190
- deviceFingerprint: deviceFingerprint ?? null,
191
- }).returning();
192
-
193
- try {
194
- const sessions = new SessionRepository();
195
- await sessions.create({
196
- userId: user.id,
197
- refreshTokenId: inserted.id,
198
- deviceFingerprint,
199
- ipAddress: ip,
200
- userAgent,
201
- expiresAt,
202
- });
203
- } catch {
204
- // Session tracking is best-effort; token creation must not fail because of it.
205
- }
206
-
207
- return { accessToken, refreshToken, refreshTokenHash, expiresAt };
208
- }
209
-
210
- export async function verifyAccessToken(token: string): Promise<TokenClaims> {
211
- if (!activeKey) await loadSigningKeys();
212
-
213
- const header = decodeProtectedHeader(token);
214
- const keyPair = header.kid ? validKeys.get(header.kid) : undefined;
215
- const publicKey = keyPair?.publicKey ?? activeKey?.publicKey;
216
-
217
- if (!publicKey) {
218
- throw new Error("JWT signing keys not loaded");
219
- }
220
-
221
- const { payload } = await jwtVerify(token, publicKey, {
222
- issuer: issuer(),
223
- audience: "hilbras",
224
- });
225
- return payload as unknown as TokenClaims;
226
- }
227
-
228
- export async function rotateRefreshToken(
229
- token: string,
230
- ip?: string,
231
- userAgent?: string
232
- ): Promise<TokenSet | null> {
233
- const hash = hashToken(token);
234
- const now = new Date();
235
-
236
- const [existing] = await db
237
- .select()
238
- .from(refreshTokens)
239
- .where(
240
- and(
241
- eq(refreshTokens.tokenHash, hash),
242
- gt(refreshTokens.expiresAt, now),
243
- isNull(refreshTokens.revokedAt)
244
- )
245
- )
246
- .limit(1);
247
-
248
- if (!existing) return null;
249
-
250
- // Revoke old token immediately.
251
- await db
252
- .update(refreshTokens)
253
- .set({ revokedAt: now })
254
- .where(eq(refreshTokens.id, existing.id));
255
-
256
- const [user] = await db.select().from(users).where(eq(users.id, existing.userId)).limit(1);
257
- if (!user) return null;
258
-
259
- return createTokenSet(
260
- user,
261
- ip,
262
- userAgent,
263
- {
264
- appId: existing.appId ?? undefined,
265
- orgId: undefined,
266
- clientId: undefined,
267
- deviceFingerprint: existing.deviceFingerprint ?? undefined,
268
- },
269
- existing.deviceFingerprint ?? undefined
270
- );
271
- }
272
-
273
- export async function revokeRefreshToken(token: string): Promise<void> {
274
- const hash = hashToken(token);
275
- await db.update(refreshTokens).set({ revokedAt: new Date() }).where(eq(refreshTokens.tokenHash, hash));
276
- }
277
-
278
- export async function revokeAllUserRefreshTokens(userId: string): Promise<void> {
279
- await db.update(refreshTokens).set({ revokedAt: new Date() }).where(eq(refreshTokens.userId, userId));
280
- }
281
-
282
- function hashToken(token: string): string {
283
- return crypto.createHash("sha256").update(token).digest("hex");
284
- }
285
-
286
- // Re-exported from secrets service for backwards compatibility.
287
- export { hashApiKey, generateApiKey } from "./secrets.js";
@@ -1,113 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { eq, and, isNull } from "drizzle-orm";
3
- import { Secret, TOTP } from "otpauth";
4
- import { config } from "../config.js";
5
- import { db } from "../db/index.js";
6
- import { totpBackupCodes } from "../db/schema.js";
7
-
8
- const ALGORITHM = "aes-256-cbc";
9
- const IV_LENGTH = 16;
10
-
11
- function getEncryptionKey(): Buffer {
12
- const raw = config.TOTP_ENCRYPTION_KEY || config.INTERNAL_API_KEY;
13
- if (raw && raw.length >= 32) {
14
- return Buffer.from(raw.slice(0, 32));
15
- }
16
- return crypto.createHash("sha256").update(raw || "keystone-totp-default").digest();
17
- }
18
-
19
- export function generateSecret(): string {
20
- return new Secret({ size: 20 }).base32;
21
- }
22
-
23
- export function buildProvisioningUri(input: { secret: string; email: string; issuer?: string }): string {
24
- const issuer = input.issuer || config.TOTP_ISSUER;
25
- const totp = new TOTP({
26
- issuer,
27
- label: input.email,
28
- algorithm: "SHA1",
29
- digits: 6,
30
- period: 30,
31
- secret: Secret.fromBase32(input.secret),
32
- });
33
- return totp.toString();
34
- }
35
-
36
- export function verifyTOTP(secret: string, code: string, window = 1): boolean {
37
- try {
38
- const totp = new TOTP({
39
- algorithm: "SHA1",
40
- digits: 6,
41
- period: 30,
42
- secret: Secret.fromBase32(secret),
43
- });
44
- const delta = totp.validate({ token: code, window });
45
- return delta !== null;
46
- } catch {
47
- return false;
48
- }
49
- }
50
-
51
- export function encryptSecret(secret: string): string {
52
- const key = getEncryptionKey();
53
- const iv = crypto.randomBytes(IV_LENGTH);
54
- const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
55
- const encrypted = Buffer.concat([cipher.update(secret, "utf8"), cipher.final()]);
56
- return `${iv.toString("base64url")}:${encrypted.toString("base64url")}`;
57
- }
58
-
59
- export function decryptSecret(encrypted: string): string {
60
- const [ivBase64, dataBase64] = encrypted.split(":");
61
- if (!ivBase64 || !dataBase64) throw new Error("Invalid encrypted secret format");
62
- const key = getEncryptionKey();
63
- const iv = Buffer.from(ivBase64, "base64url");
64
- const encryptedData = Buffer.from(dataBase64, "base64url");
65
- const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
66
- const decrypted = Buffer.concat([decipher.update(encryptedData), decipher.final()]);
67
- return decrypted.toString("utf8");
68
- }
69
-
70
- export function generateBackupCodes(): { codes: string[]; hashes: string[] } {
71
- const codes: string[] = [];
72
- const hashes: string[] = [];
73
- for (let i = 0; i < 10; i++) {
74
- const code = crypto.randomBytes(4).toString("hex").toLowerCase();
75
- codes.push(code);
76
- hashes.push(crypto.createHash("sha256").update(code).digest("hex"));
77
- }
78
- return { codes, hashes };
79
- }
80
-
81
- export async function storeBackupCodes(userId: string, codeHashes: string[]): Promise<void> {
82
- if (codeHashes.length === 0) return;
83
- await db.delete(totpBackupCodes).where(eq(totpBackupCodes.userId, userId));
84
- await db.insert(totpBackupCodes).values(
85
- codeHashes.map((hash) => ({ userId, codeHash: hash }))
86
- );
87
- }
88
-
89
- export async function verifyBackupCode(userId: string, code: string): Promise<boolean> {
90
- const codeHash = crypto.createHash("sha256").update(code).digest("hex");
91
- const now = new Date();
92
-
93
- const [record] = await db
94
- .select()
95
- .from(totpBackupCodes)
96
- .where(
97
- and(
98
- eq(totpBackupCodes.userId, userId),
99
- eq(totpBackupCodes.codeHash, codeHash),
100
- isNull(totpBackupCodes.usedAt)
101
- )
102
- )
103
- .limit(1);
104
-
105
- if (!record) return false;
106
-
107
- await db
108
- .update(totpBackupCodes)
109
- .set({ usedAt: now })
110
- .where(eq(totpBackupCodes.id, record.id));
111
-
112
- return true;
113
- }
@@ -1,239 +0,0 @@
1
- import { eq, sql } from "drizzle-orm";
2
- import { db } from "../db/index.js";
3
- import { users, userIdentities, identityProviders, orgMemberships, type User } from "../db/schema.js";
4
-
5
- export interface OAuthClaims {
6
- sub: string;
7
- email: string;
8
- username?: string;
9
- name?: string;
10
- picture?: string;
11
- email_verified?: boolean;
12
- }
13
-
14
- export async function findUserByEmail(email: string): Promise<User | undefined> {
15
- const [user] = await db.select().from(users).where(eq(users.email, email.toLowerCase())).limit(1);
16
- return user;
17
- }
18
-
19
- export async function findUserById(id: string): Promise<User | undefined> {
20
- const [user] = await db.select().from(users).where(eq(users.id, id)).limit(1);
21
- return user;
22
- }
23
-
24
- export async function findUserByZitadelId(zitadelUserId: string): Promise<User | undefined> {
25
- const [user] = await db.select().from(users).where(eq(users.zitadelUserId, zitadelUserId)).limit(1);
26
- return user;
27
- }
28
-
29
- export async function createPasswordUser(input: {
30
- zitadelUserId?: string;
31
- passwordHash?: string;
32
- username: string;
33
- email: string;
34
- name: string;
35
- emailVerified?: boolean;
36
- }): Promise<User> {
37
- const [user] = await db
38
- .insert(users)
39
- .values({
40
- zitadelUserId: input.zitadelUserId ?? null,
41
- passwordHash: input.passwordHash ?? null,
42
- username: slugifyUsername(input.username),
43
- email: input.email.toLowerCase().trim(),
44
- name: input.name.trim() || input.username,
45
- provider: "password",
46
- emailVerified: input.emailVerified ?? true,
47
- })
48
- .returning();
49
- return user;
50
- }
51
-
52
- export async function upsertOAuthUser(
53
- claims: OAuthClaims,
54
- providerType: string,
55
- providerId?: string
56
- ): Promise<User> {
57
- const username = slugifyUsername(claims.username || claims.name || claims.email.split("@")[0]);
58
- const email = claims.email.toLowerCase().trim();
59
-
60
- // Prefer linking by external identity when a provider record is available.
61
- if (providerId) {
62
- const [existingLink] = await db
63
- .select({ user: users })
64
- .from(userIdentities)
65
- .where(eq(userIdentities.externalSub, claims.sub))
66
- .innerJoin(users, eq(userIdentities.userId, users.id))
67
- .limit(1);
68
-
69
- if (existingLink) {
70
- const existing = existingLink.user;
71
- const [updated] = await db
72
- .update(users)
73
- .set({
74
- email,
75
- username: await ensureUniqueUsername(username, existing.id),
76
- name: claims.name || existing.name,
77
- avatarUrl: claims.picture || existing.avatarUrl,
78
- emailVerified: claims.email_verified ?? existing.emailVerified ?? true,
79
- provider: providerType,
80
- updatedAt: sql`now()`,
81
- })
82
- .where(eq(users.id, existing.id))
83
- .returning();
84
- return updated;
85
- }
86
- }
87
-
88
- // Fall back to email-based matching.
89
- const existing = await findUserByEmail(email);
90
- if (existing) {
91
- const [updated] = await db
92
- .update(users)
93
- .set({
94
- email,
95
- username: await ensureUniqueUsername(username, existing.id),
96
- name: claims.name || existing.name,
97
- avatarUrl: claims.picture || existing.avatarUrl,
98
- emailVerified: claims.email_verified ?? existing.emailVerified ?? true,
99
- provider: providerType,
100
- updatedAt: sql`now()`,
101
- })
102
- .where(eq(users.id, existing.id))
103
- .returning();
104
- return updated;
105
- }
106
-
107
- const [user] = await db
108
- .insert(users)
109
- .values({
110
- email,
111
- username: await ensureUniqueUsername(username),
112
- name: claims.name || username,
113
- avatarUrl: claims.picture,
114
- emailVerified: claims.email_verified ?? true,
115
- provider: providerType,
116
- })
117
- .returning();
118
-
119
- if (providerId) {
120
- await db.insert(userIdentities).values({
121
- userId: user.id,
122
- providerId,
123
- providerType,
124
- externalSub: claims.sub,
125
- email,
126
- profile: { name: claims.name, picture: claims.picture, username: claims.username },
127
- });
128
- }
129
-
130
- return user;
131
- }
132
-
133
- export async function linkUserIdentity(
134
- userId: string,
135
- providerId: string,
136
- providerType: string,
137
- externalSub: string,
138
- email?: string,
139
- profile?: Record<string, unknown>
140
- ): Promise<void> {
141
- const [provider] = await db.select().from(identityProviders).where(eq(identityProviders.id, providerId)).limit(1);
142
- if (!provider) throw new Error("Identity provider not found");
143
- await db
144
- .insert(userIdentities)
145
- .values({
146
- userId,
147
- providerId,
148
- providerType,
149
- externalSub,
150
- email,
151
- profile: profile ?? {},
152
- })
153
- .onConflictDoNothing({ target: [userIdentities.providerId, userIdentities.externalSub] });
154
- }
155
-
156
- export async function updateUserLastSeen(id: string): Promise<void> {
157
- await db.update(users).set({ updatedAt: sql`now()` }).where(eq(users.id, id));
158
- }
159
-
160
- export async function findOrCreateUserByEmail(input: {
161
- email: string;
162
- name?: string;
163
- username?: string;
164
- }): Promise<User> {
165
- const existing = await findUserByEmail(input.email);
166
- if (existing) return existing;
167
-
168
- const baseUsername = input.username || input.email.split("@")[0];
169
- const username = await ensureUniqueUsername(slugifyUsername(baseUsername));
170
-
171
- const [user] = await db
172
- .insert(users)
173
- .values({
174
- email: input.email.toLowerCase().trim(),
175
- username,
176
- name: input.name || username,
177
- provider: "password",
178
- emailVerified: false,
179
- })
180
- .returning();
181
- return user;
182
- }
183
-
184
- export async function listUsersByOrg(orgId: string): Promise<User[]> {
185
- const rows = await db
186
- .select({ user: users })
187
- .from(users)
188
- .innerJoin(orgMemberships, eq(users.id, orgMemberships.userId))
189
- .where(eq(orgMemberships.orgId, orgId));
190
- return rows.map((r) => r.user);
191
- }
192
-
193
- export async function updateUser(
194
- userId: string,
195
- updates: Partial<{
196
- name: string;
197
- username: string;
198
- role: string;
199
- emailVerified: boolean;
200
- }>
201
- ): Promise<User | undefined> {
202
- const [updated] = await db
203
- .update(users)
204
- .set({ ...updates, updatedAt: sql`now()` })
205
- .where(eq(users.id, userId))
206
- .returning();
207
- return updated;
208
- }
209
-
210
- export async function deactivateUser(userId: string): Promise<void> {
211
- await db.update(users).set({ emailVerified: false, updatedAt: sql`now()` }).where(eq(users.id, userId));
212
- }
213
-
214
- export function slugifyUsername(input: string): string {
215
- return input
216
- .toLowerCase()
217
- .trim()
218
- .replace(/[^a-z0-9_-]+/g, "-")
219
- .replace(/^-+|-+$/g, "")
220
- .slice(0, 32);
221
- }
222
-
223
- export async function ensureUniqueUsername(base: string, excludeId?: string): Promise<string> {
224
- let username = base || "user";
225
- let counter = 2;
226
- while (true) {
227
- const existing = await db
228
- .select({ id: users.id })
229
- .from(users)
230
- .where(eq(users.username, username))
231
- .limit(1);
232
- if (existing.length === 0 || existing[0].id === excludeId) {
233
- return username;
234
- }
235
- username = `${base}-${counter}`;
236
- counter++;
237
- }
238
- }
239
-