@atlasauth/cli 0.24.0 → 0.25.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 (530) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +4 -4
  3. package/dist/args.d.ts +0 -601
  4. package/dist/args.js +0 -289
  5. package/dist/args.js.map +0 -1
  6. package/dist/cli.d.ts +0 -2
  7. package/dist/cli.js +0 -19
  8. package/dist/cli.js.map +0 -1
  9. package/dist/commands/actions-gallery.d.ts +0 -8
  10. package/dist/commands/actions-gallery.js +0 -197
  11. package/dist/commands/actions-gallery.js.map +0 -1
  12. package/dist/commands/actions.d.ts +0 -13
  13. package/dist/commands/actions.js +0 -135
  14. package/dist/commands/actions.js.map +0 -1
  15. package/dist/commands/admin.d.ts +0 -49
  16. package/dist/commands/admin.js +0 -353
  17. package/dist/commands/admin.js.map +0 -1
  18. package/dist/commands/api-keys.d.ts +0 -4
  19. package/dist/commands/api-keys.js +0 -96
  20. package/dist/commands/api-keys.js.map +0 -1
  21. package/dist/commands/auth.d.ts +0 -25
  22. package/dist/commands/auth.js +0 -102
  23. package/dist/commands/auth.js.map +0 -1
  24. package/dist/commands/config.d.ts +0 -104
  25. package/dist/commands/config.js +0 -1506
  26. package/dist/commands/config.js.map +0 -1
  27. package/dist/commands/csp.d.ts +0 -32
  28. package/dist/commands/csp.js +0 -180
  29. package/dist/commands/csp.js.map +0 -1
  30. package/dist/commands/dev.d.ts +0 -8
  31. package/dist/commands/dev.js +0 -84
  32. package/dist/commands/dev.js.map +0 -1
  33. package/dist/commands/fga.d.ts +0 -10
  34. package/dist/commands/fga.js +0 -146
  35. package/dist/commands/fga.js.map +0 -1
  36. package/dist/commands/golive.d.ts +0 -40
  37. package/dist/commands/golive.js +0 -285
  38. package/dist/commands/golive.js.map +0 -1
  39. package/dist/commands/id-accounts.d.ts +0 -13
  40. package/dist/commands/id-accounts.js +0 -195
  41. package/dist/commands/id-accounts.js.map +0 -1
  42. package/dist/commands/import-better-auth.d.ts +0 -3
  43. package/dist/commands/import-better-auth.js +0 -164
  44. package/dist/commands/import-better-auth.js.map +0 -1
  45. package/dist/commands/import.d.ts +0 -3
  46. package/dist/commands/import.js +0 -123
  47. package/dist/commands/import.js.map +0 -1
  48. package/dist/commands/info.d.ts +0 -75
  49. package/dist/commands/info.js +0 -362
  50. package/dist/commands/info.js.map +0 -1
  51. package/dist/commands/init.d.ts +0 -3
  52. package/dist/commands/init.js +0 -438
  53. package/dist/commands/init.js.map +0 -1
  54. package/dist/commands/integrations.d.ts +0 -8
  55. package/dist/commands/integrations.js +0 -112
  56. package/dist/commands/integrations.js.map +0 -1
  57. package/dist/commands/listen.d.ts +0 -17
  58. package/dist/commands/listen.js +0 -223
  59. package/dist/commands/listen.js.map +0 -1
  60. package/dist/commands/mcp.d.ts +0 -38
  61. package/dist/commands/mcp.js +0 -111
  62. package/dist/commands/mcp.js.map +0 -1
  63. package/dist/commands/migrate.d.ts +0 -16
  64. package/dist/commands/migrate.js +0 -114
  65. package/dist/commands/migrate.js.map +0 -1
  66. package/dist/commands/move-origin.d.ts +0 -11
  67. package/dist/commands/move-origin.js +0 -95
  68. package/dist/commands/move-origin.js.map +0 -1
  69. package/dist/commands/operator.d.ts +0 -18
  70. package/dist/commands/operator.js +0 -238
  71. package/dist/commands/operator.js.map +0 -1
  72. package/dist/commands/orgs.d.ts +0 -4
  73. package/dist/commands/orgs.js +0 -72
  74. package/dist/commands/orgs.js.map +0 -1
  75. package/dist/commands/pages.d.ts +0 -14
  76. package/dist/commands/pages.js +0 -113
  77. package/dist/commands/pages.js.map +0 -1
  78. package/dist/commands/partner-platforms.d.ts +0 -10
  79. package/dist/commands/partner-platforms.js +0 -157
  80. package/dist/commands/partner-platforms.js.map +0 -1
  81. package/dist/commands/project-commands.d.ts +0 -38
  82. package/dist/commands/project-commands.js +0 -361
  83. package/dist/commands/project-commands.js.map +0 -1
  84. package/dist/commands/referrals.d.ts +0 -69
  85. package/dist/commands/referrals.js +0 -1056
  86. package/dist/commands/referrals.js.map +0 -1
  87. package/dist/commands/resources.d.ts +0 -44
  88. package/dist/commands/resources.js +0 -234
  89. package/dist/commands/resources.js.map +0 -1
  90. package/dist/commands/sessions.d.ts +0 -4
  91. package/dist/commands/sessions.js +0 -28
  92. package/dist/commands/sessions.js.map +0 -1
  93. package/dist/commands/shared.d.ts +0 -38
  94. package/dist/commands/shared.js +0 -69
  95. package/dist/commands/shared.js.map +0 -1
  96. package/dist/commands/status.d.ts +0 -3
  97. package/dist/commands/status.js +0 -77
  98. package/dist/commands/status.js.map +0 -1
  99. package/dist/commands/users.d.ts +0 -4
  100. package/dist/commands/users.js +0 -100
  101. package/dist/commands/users.js.map +0 -1
  102. package/dist/commands/webhooks.d.ts +0 -34
  103. package/dist/commands/webhooks.js +0 -301
  104. package/dist/commands/webhooks.js.map +0 -1
  105. package/dist/config-http.d.ts +0 -29
  106. package/dist/config-http.js +0 -64
  107. package/dist/config-http.js.map +0 -1
  108. package/dist/config.d.ts +0 -64
  109. package/dist/config.js +0 -69
  110. package/dist/config.js.map +0 -1
  111. package/dist/context.d.ts +0 -72
  112. package/dist/context.js +0 -27
  113. package/dist/context.js.map +0 -1
  114. package/dist/define-config.d.ts +0 -9
  115. package/dist/define-config.js +0 -8
  116. package/dist/define-config.js.map +0 -1
  117. package/dist/errors.d.ts +0 -15
  118. package/dist/errors.js +0 -25
  119. package/dist/errors.js.map +0 -1
  120. package/dist/help.d.ts +0 -8
  121. package/dist/help.js +0 -868
  122. package/dist/help.js.map +0 -1
  123. package/dist/import/csv.d.ts +0 -6
  124. package/dist/import/csv.js +0 -63
  125. package/dist/import/csv.js.map +0 -1
  126. package/dist/import/vendors.d.ts +0 -57
  127. package/dist/import/vendors.js +0 -568
  128. package/dist/import/vendors.js.map +0 -1
  129. package/dist/index.d.ts +0 -33
  130. package/dist/index.js +0 -81
  131. package/dist/index.js.map +0 -1
  132. package/dist/io.d.ts +0 -21
  133. package/dist/io.js +0 -28
  134. package/dist/io.js.map +0 -1
  135. package/dist/migrate/appwrite/plugin.d.ts +0 -2
  136. package/dist/migrate/appwrite/plugin.js +0 -103
  137. package/dist/migrate/appwrite/plugin.js.map +0 -1
  138. package/dist/migrate/auth0/plugin.d.ts +0 -2
  139. package/dist/migrate/auth0/plugin.js +0 -126
  140. package/dist/migrate/auth0/plugin.js.map +0 -1
  141. package/dist/migrate/authentik/plugin.d.ts +0 -2
  142. package/dist/migrate/authentik/plugin.js +0 -135
  143. package/dist/migrate/authentik/plugin.js.map +0 -1
  144. package/dist/migrate/azure-ad-b2c/plugin.d.ts +0 -8
  145. package/dist/migrate/azure-ad-b2c/plugin.js +0 -165
  146. package/dist/migrate/azure-ad-b2c/plugin.js.map +0 -1
  147. package/dist/migrate/better-auth/integration.d.ts +0 -59
  148. package/dist/migrate/better-auth/integration.js +0 -81
  149. package/dist/migrate/better-auth/integration.js.map +0 -1
  150. package/dist/migrate/better-auth/orchestrator.d.ts +0 -43
  151. package/dist/migrate/better-auth/orchestrator.js +0 -525
  152. package/dist/migrate/better-auth/orchestrator.js.map +0 -1
  153. package/dist/migrate/better-auth/output.d.ts +0 -20
  154. package/dist/migrate/better-auth/output.js +0 -146
  155. package/dist/migrate/better-auth/output.js.map +0 -1
  156. package/dist/migrate/better-auth/translate.d.ts +0 -77
  157. package/dist/migrate/better-auth/translate.js +0 -1989
  158. package/dist/migrate/better-auth/translate.js.map +0 -1
  159. package/dist/migrate/clerk/plugin.d.ts +0 -2
  160. package/dist/migrate/clerk/plugin.js +0 -76
  161. package/dist/migrate/clerk/plugin.js.map +0 -1
  162. package/dist/migrate/cognito/plugin.d.ts +0 -5
  163. package/dist/migrate/cognito/plugin.js +0 -170
  164. package/dist/migrate/cognito/plugin.js.map +0 -1
  165. package/dist/migrate/corbado/plugin.d.ts +0 -2
  166. package/dist/migrate/corbado/plugin.js +0 -63
  167. package/dist/migrate/corbado/plugin.js.map +0 -1
  168. package/dist/migrate/descope/plugin.d.ts +0 -2
  169. package/dist/migrate/descope/plugin.js +0 -83
  170. package/dist/migrate/descope/plugin.js.map +0 -1
  171. package/dist/migrate/entra-external-id/plugin.d.ts +0 -8
  172. package/dist/migrate/entra-external-id/plugin.js +0 -12
  173. package/dist/migrate/entra-external-id/plugin.js.map +0 -1
  174. package/dist/migrate/export/appwrite-config.d.ts +0 -28
  175. package/dist/migrate/export/appwrite-config.js +0 -170
  176. package/dist/migrate/export/appwrite-config.js.map +0 -1
  177. package/dist/migrate/export/appwrite.d.ts +0 -51
  178. package/dist/migrate/export/appwrite.js +0 -288
  179. package/dist/migrate/export/appwrite.js.map +0 -1
  180. package/dist/migrate/export/auth0-config.d.ts +0 -29
  181. package/dist/migrate/export/auth0-config.js +0 -249
  182. package/dist/migrate/export/auth0-config.js.map +0 -1
  183. package/dist/migrate/export/auth0.d.ts +0 -62
  184. package/dist/migrate/export/auth0.js +0 -575
  185. package/dist/migrate/export/auth0.js.map +0 -1
  186. package/dist/migrate/export/authentik-config.d.ts +0 -45
  187. package/dist/migrate/export/authentik-config.js +0 -357
  188. package/dist/migrate/export/authentik-config.js.map +0 -1
  189. package/dist/migrate/export/authentik.d.ts +0 -110
  190. package/dist/migrate/export/authentik.js +0 -838
  191. package/dist/migrate/export/authentik.js.map +0 -1
  192. package/dist/migrate/export/azure-config.d.ts +0 -58
  193. package/dist/migrate/export/azure-config.js +0 -344
  194. package/dist/migrate/export/azure-config.js.map +0 -1
  195. package/dist/migrate/export/azure.d.ts +0 -85
  196. package/dist/migrate/export/azure.js +0 -373
  197. package/dist/migrate/export/azure.js.map +0 -1
  198. package/dist/migrate/export/clerk-config.d.ts +0 -26
  199. package/dist/migrate/export/clerk-config.js +0 -227
  200. package/dist/migrate/export/clerk-config.js.map +0 -1
  201. package/dist/migrate/export/clerk.d.ts +0 -46
  202. package/dist/migrate/export/clerk.js +0 -486
  203. package/dist/migrate/export/clerk.js.map +0 -1
  204. package/dist/migrate/export/cognito-config.d.ts +0 -25
  205. package/dist/migrate/export/cognito-config.js +0 -273
  206. package/dist/migrate/export/cognito-config.js.map +0 -1
  207. package/dist/migrate/export/cognito.d.ts +0 -103
  208. package/dist/migrate/export/cognito.js +0 -441
  209. package/dist/migrate/export/cognito.js.map +0 -1
  210. package/dist/migrate/export/corbado-config.d.ts +0 -20
  211. package/dist/migrate/export/corbado-config.js +0 -63
  212. package/dist/migrate/export/corbado-config.js.map +0 -1
  213. package/dist/migrate/export/corbado.d.ts +0 -37
  214. package/dist/migrate/export/corbado.js +0 -132
  215. package/dist/migrate/export/corbado.js.map +0 -1
  216. package/dist/migrate/export/descope.d.ts +0 -35
  217. package/dist/migrate/export/descope.js +0 -208
  218. package/dist/migrate/export/descope.js.map +0 -1
  219. package/dist/migrate/export/fake-vendor.test-helper.d.ts +0 -27
  220. package/dist/migrate/export/fake-vendor.test-helper.js +0 -41
  221. package/dist/migrate/export/fake-vendor.test-helper.js.map +0 -1
  222. package/dist/migrate/export/firebase-config.d.ts +0 -24
  223. package/dist/migrate/export/firebase-config.js +0 -215
  224. package/dist/migrate/export/firebase-config.js.map +0 -1
  225. package/dist/migrate/export/firebase.d.ts +0 -102
  226. package/dist/migrate/export/firebase.js +0 -464
  227. package/dist/migrate/export/firebase.js.map +0 -1
  228. package/dist/migrate/export/frameworks/app-users.d.ts +0 -42
  229. package/dist/migrate/export/frameworks/app-users.js +0 -161
  230. package/dist/migrate/export/frameworks/app-users.js.map +0 -1
  231. package/dist/migrate/export/frameworks/authjs.d.ts +0 -41
  232. package/dist/migrate/export/frameworks/authjs.js +0 -146
  233. package/dist/migrate/export/frameworks/authjs.js.map +0 -1
  234. package/dist/migrate/export/frameworks/devise.d.ts +0 -39
  235. package/dist/migrate/export/frameworks/devise.js +0 -218
  236. package/dist/migrate/export/frameworks/devise.js.map +0 -1
  237. package/dist/migrate/export/frameworks/django.d.ts +0 -45
  238. package/dist/migrate/export/frameworks/django.js +0 -315
  239. package/dist/migrate/export/frameworks/django.js.map +0 -1
  240. package/dist/migrate/export/frameworks/lucia.d.ts +0 -42
  241. package/dist/migrate/export/frameworks/lucia.js +0 -263
  242. package/dist/migrate/export/frameworks/lucia.js.map +0 -1
  243. package/dist/migrate/export/frameworks/tables.d.ts +0 -90
  244. package/dist/migrate/export/frameworks/tables.js +0 -325
  245. package/dist/migrate/export/frameworks/tables.js.map +0 -1
  246. package/dist/migrate/export/frameworks/webauthn.d.ts +0 -25
  247. package/dist/migrate/export/frameworks/webauthn.js +0 -130
  248. package/dist/migrate/export/frameworks/webauthn.js.map +0 -1
  249. package/dist/migrate/export/frontegg-config.d.ts +0 -29
  250. package/dist/migrate/export/frontegg-config.js +0 -238
  251. package/dist/migrate/export/frontegg-config.js.map +0 -1
  252. package/dist/migrate/export/frontegg.d.ts +0 -67
  253. package/dist/migrate/export/frontegg.js +0 -410
  254. package/dist/migrate/export/frontegg.js.map +0 -1
  255. package/dist/migrate/export/fusionauth-config.d.ts +0 -26
  256. package/dist/migrate/export/fusionauth-config.js +0 -226
  257. package/dist/migrate/export/fusionauth-config.js.map +0 -1
  258. package/dist/migrate/export/fusionauth.d.ts +0 -99
  259. package/dist/migrate/export/fusionauth.js +0 -642
  260. package/dist/migrate/export/fusionauth.js.map +0 -1
  261. package/dist/migrate/export/hanko-config.d.ts +0 -27
  262. package/dist/migrate/export/hanko-config.js +0 -265
  263. package/dist/migrate/export/hanko-config.js.map +0 -1
  264. package/dist/migrate/export/hanko.d.ts +0 -52
  265. package/dist/migrate/export/hanko.js +0 -605
  266. package/dist/migrate/export/hanko.js.map +0 -1
  267. package/dist/migrate/export/keycloak-config.d.ts +0 -19
  268. package/dist/migrate/export/keycloak-config.js +0 -219
  269. package/dist/migrate/export/keycloak-config.js.map +0 -1
  270. package/dist/migrate/export/keycloak.d.ts +0 -155
  271. package/dist/migrate/export/keycloak.js +0 -878
  272. package/dist/migrate/export/keycloak.js.map +0 -1
  273. package/dist/migrate/export/kinde-descope-config.d.ts +0 -38
  274. package/dist/migrate/export/kinde-descope-config.js +0 -172
  275. package/dist/migrate/export/kinde-descope-config.js.map +0 -1
  276. package/dist/migrate/export/kinde.d.ts +0 -57
  277. package/dist/migrate/export/kinde.js +0 -333
  278. package/dist/migrate/export/kinde.js.map +0 -1
  279. package/dist/migrate/export/ldap.d.ts +0 -53
  280. package/dist/migrate/export/ldap.js +0 -277
  281. package/dist/migrate/export/ldap.js.map +0 -1
  282. package/dist/migrate/export/logto-config.d.ts +0 -27
  283. package/dist/migrate/export/logto-config.js +0 -264
  284. package/dist/migrate/export/logto-config.js.map +0 -1
  285. package/dist/migrate/export/logto.d.ts +0 -150
  286. package/dist/migrate/export/logto.js +0 -809
  287. package/dist/migrate/export/logto.js.map +0 -1
  288. package/dist/migrate/export/magic-config.d.ts +0 -14
  289. package/dist/migrate/export/magic-config.js +0 -28
  290. package/dist/migrate/export/magic-config.js.map +0 -1
  291. package/dist/migrate/export/magic.d.ts +0 -31
  292. package/dist/migrate/export/magic.js +0 -93
  293. package/dist/migrate/export/magic.js.map +0 -1
  294. package/dist/migrate/export/mini-yaml.d.ts +0 -19
  295. package/dist/migrate/export/mini-yaml.js +0 -581
  296. package/dist/migrate/export/mini-yaml.js.map +0 -1
  297. package/dist/migrate/export/nhost-config.d.ts +0 -26
  298. package/dist/migrate/export/nhost-config.js +0 -360
  299. package/dist/migrate/export/nhost-config.js.map +0 -1
  300. package/dist/migrate/export/nhost.d.ts +0 -64
  301. package/dist/migrate/export/nhost.js +0 -304
  302. package/dist/migrate/export/nhost.js.map +0 -1
  303. package/dist/migrate/export/okta-config.d.ts +0 -30
  304. package/dist/migrate/export/okta-config.js +0 -205
  305. package/dist/migrate/export/okta-config.js.map +0 -1
  306. package/dist/migrate/export/okta.d.ts +0 -43
  307. package/dist/migrate/export/okta.js +0 -337
  308. package/dist/migrate/export/okta.js.map +0 -1
  309. package/dist/migrate/export/onelogin.d.ts +0 -22
  310. package/dist/migrate/export/onelogin.js +0 -123
  311. package/dist/migrate/export/onelogin.js.map +0 -1
  312. package/dist/migrate/export/ory-config.d.ts +0 -58
  313. package/dist/migrate/export/ory-config.js +0 -451
  314. package/dist/migrate/export/ory-config.js.map +0 -1
  315. package/dist/migrate/export/ory.d.ts +0 -81
  316. package/dist/migrate/export/ory.js +0 -555
  317. package/dist/migrate/export/ory.js.map +0 -1
  318. package/dist/migrate/export/password-detect.d.ts +0 -29
  319. package/dist/migrate/export/password-detect.js +0 -81
  320. package/dist/migrate/export/password-detect.js.map +0 -1
  321. package/dist/migrate/export/pingone.d.ts +0 -36
  322. package/dist/migrate/export/pingone.js +0 -218
  323. package/dist/migrate/export/pingone.js.map +0 -1
  324. package/dist/migrate/export/plugin-kit.d.ts +0 -25
  325. package/dist/migrate/export/plugin-kit.js +0 -82
  326. package/dist/migrate/export/plugin-kit.js.map +0 -1
  327. package/dist/migrate/export/pocketbase-config.d.ts +0 -28
  328. package/dist/migrate/export/pocketbase-config.js +0 -180
  329. package/dist/migrate/export/pocketbase-config.js.map +0 -1
  330. package/dist/migrate/export/pocketbase.d.ts +0 -52
  331. package/dist/migrate/export/pocketbase.js +0 -243
  332. package/dist/migrate/export/pocketbase.js.map +0 -1
  333. package/dist/migrate/export/project-files.d.ts +0 -15
  334. package/dist/migrate/export/project-files.js +0 -43
  335. package/dist/migrate/export/project-files.js.map +0 -1
  336. package/dist/migrate/export/propelauth-config.d.ts +0 -18
  337. package/dist/migrate/export/propelauth-config.js +0 -58
  338. package/dist/migrate/export/propelauth-config.js.map +0 -1
  339. package/dist/migrate/export/propelauth-harness.test-helper.d.ts +0 -62
  340. package/dist/migrate/export/propelauth-harness.test-helper.js +0 -109
  341. package/dist/migrate/export/propelauth-harness.test-helper.js.map +0 -1
  342. package/dist/migrate/export/propelauth.d.ts +0 -48
  343. package/dist/migrate/export/propelauth.js +0 -255
  344. package/dist/migrate/export/propelauth.js.map +0 -1
  345. package/dist/migrate/export/record-set.d.ts +0 -44
  346. package/dist/migrate/export/record-set.js +0 -98
  347. package/dist/migrate/export/record-set.js.map +0 -1
  348. package/dist/migrate/export/source-lines.d.ts +0 -17
  349. package/dist/migrate/export/source-lines.js +0 -43
  350. package/dist/migrate/export/source-lines.js.map +0 -1
  351. package/dist/migrate/export/sso-metadata.d.ts +0 -47
  352. package/dist/migrate/export/sso-metadata.js +0 -180
  353. package/dist/migrate/export/sso-metadata.js.map +0 -1
  354. package/dist/migrate/export/stytch-config.d.ts +0 -22
  355. package/dist/migrate/export/stytch-config.js +0 -102
  356. package/dist/migrate/export/stytch-config.js.map +0 -1
  357. package/dist/migrate/export/stytch.d.ts +0 -68
  358. package/dist/migrate/export/stytch.js +0 -510
  359. package/dist/migrate/export/stytch.js.map +0 -1
  360. package/dist/migrate/export/supabase-config.d.ts +0 -48
  361. package/dist/migrate/export/supabase-config.js +0 -408
  362. package/dist/migrate/export/supabase-config.js.map +0 -1
  363. package/dist/migrate/export/supabase.d.ts +0 -86
  364. package/dist/migrate/export/supabase.js +0 -524
  365. package/dist/migrate/export/supabase.js.map +0 -1
  366. package/dist/migrate/export/supertokens-config.d.ts +0 -20
  367. package/dist/migrate/export/supertokens-config.js +0 -150
  368. package/dist/migrate/export/supertokens-config.js.map +0 -1
  369. package/dist/migrate/export/supertokens.d.ts +0 -125
  370. package/dist/migrate/export/supertokens.js +0 -464
  371. package/dist/migrate/export/supertokens.js.map +0 -1
  372. package/dist/migrate/export/table.d.ts +0 -35
  373. package/dist/migrate/export/table.js +0 -248
  374. package/dist/migrate/export/table.js.map +0 -1
  375. package/dist/migrate/export/translate-kit.d.ts +0 -46
  376. package/dist/migrate/export/translate-kit.js +0 -148
  377. package/dist/migrate/export/translate-kit.js.map +0 -1
  378. package/dist/migrate/export/userfront-config.d.ts +0 -15
  379. package/dist/migrate/export/userfront-config.js +0 -49
  380. package/dist/migrate/export/userfront-config.js.map +0 -1
  381. package/dist/migrate/export/userfront.d.ts +0 -38
  382. package/dist/migrate/export/userfront.js +0 -189
  383. package/dist/migrate/export/userfront.js.map +0 -1
  384. package/dist/migrate/export/vendor-http.d.ts +0 -46
  385. package/dist/migrate/export/vendor-http.js +0 -138
  386. package/dist/migrate/export/vendor-http.js.map +0 -1
  387. package/dist/migrate/export/workos-config.d.ts +0 -23
  388. package/dist/migrate/export/workos-config.js +0 -125
  389. package/dist/migrate/export/workos-config.js.map +0 -1
  390. package/dist/migrate/export/workos.d.ts +0 -46
  391. package/dist/migrate/export/workos.js +0 -272
  392. package/dist/migrate/export/workos.js.map +0 -1
  393. package/dist/migrate/export/zip.d.ts +0 -8
  394. package/dist/migrate/export/zip.js +0 -66
  395. package/dist/migrate/export/zip.js.map +0 -1
  396. package/dist/migrate/export/zitadel-config.d.ts +0 -37
  397. package/dist/migrate/export/zitadel-config.js +0 -279
  398. package/dist/migrate/export/zitadel-config.js.map +0 -1
  399. package/dist/migrate/export/zitadel.d.ts +0 -82
  400. package/dist/migrate/export/zitadel.js +0 -447
  401. package/dist/migrate/export/zitadel.js.map +0 -1
  402. package/dist/migrate/firebase/plugin.d.ts +0 -2
  403. package/dist/migrate/firebase/plugin.js +0 -152
  404. package/dist/migrate/firebase/plugin.js.map +0 -1
  405. package/dist/migrate/framework/builtins.d.ts +0 -2
  406. package/dist/migrate/framework/builtins.js +0 -52
  407. package/dist/migrate/framework/builtins.js.map +0 -1
  408. package/dist/migrate/framework/commands.d.ts +0 -20
  409. package/dist/migrate/framework/commands.js +0 -58
  410. package/dist/migrate/framework/commands.js.map +0 -1
  411. package/dist/migrate/framework/custom.d.ts +0 -12
  412. package/dist/migrate/framework/custom.js +0 -96
  413. package/dist/migrate/framework/custom.js.map +0 -1
  414. package/dist/migrate/framework/orchestrator.d.ts +0 -113
  415. package/dist/migrate/framework/orchestrator.js +0 -532
  416. package/dist/migrate/framework/orchestrator.js.map +0 -1
  417. package/dist/migrate/framework/plugin.d.ts +0 -167
  418. package/dist/migrate/framework/plugin.js +0 -3
  419. package/dist/migrate/framework/plugin.js.map +0 -1
  420. package/dist/migrate/framework/registry.d.ts +0 -11
  421. package/dist/migrate/framework/registry.js +0 -44
  422. package/dist/migrate/framework/registry.js.map +0 -1
  423. package/dist/migrate/framework/report.d.ts +0 -17
  424. package/dist/migrate/framework/report.js +0 -103
  425. package/dist/migrate/framework/report.js.map +0 -1
  426. package/dist/migrate/frameworks/plugins.d.ts +0 -29
  427. package/dist/migrate/frameworks/plugins.js +0 -402
  428. package/dist/migrate/frameworks/plugins.js.map +0 -1
  429. package/dist/migrate/frameworks/report.d.ts +0 -92
  430. package/dist/migrate/frameworks/report.js +0 -207
  431. package/dist/migrate/frameworks/report.js.map +0 -1
  432. package/dist/migrate/frameworks/translate-js.d.ts +0 -5
  433. package/dist/migrate/frameworks/translate-js.js +0 -503
  434. package/dist/migrate/frameworks/translate-js.js.map +0 -1
  435. package/dist/migrate/frameworks/translate-rails-django.d.ts +0 -3
  436. package/dist/migrate/frameworks/translate-rails-django.js +0 -1391
  437. package/dist/migrate/frameworks/translate-rails-django.js.map +0 -1
  438. package/dist/migrate/frontegg/plugin.d.ts +0 -2
  439. package/dist/migrate/frontegg/plugin.js +0 -78
  440. package/dist/migrate/frontegg/plugin.js.map +0 -1
  441. package/dist/migrate/fusionauth/plugin.d.ts +0 -2
  442. package/dist/migrate/fusionauth/plugin.js +0 -109
  443. package/dist/migrate/fusionauth/plugin.js.map +0 -1
  444. package/dist/migrate/hanko/plugin.d.ts +0 -2
  445. package/dist/migrate/hanko/plugin.js +0 -100
  446. package/dist/migrate/hanko/plugin.js.map +0 -1
  447. package/dist/migrate/keycloak/plugin.d.ts +0 -2
  448. package/dist/migrate/keycloak/plugin.js +0 -148
  449. package/dist/migrate/keycloak/plugin.js.map +0 -1
  450. package/dist/migrate/kinde/plugin.d.ts +0 -2
  451. package/dist/migrate/kinde/plugin.js +0 -105
  452. package/dist/migrate/kinde/plugin.js.map +0 -1
  453. package/dist/migrate/ldap/plugin.d.ts +0 -2
  454. package/dist/migrate/ldap/plugin.js +0 -73
  455. package/dist/migrate/ldap/plugin.js.map +0 -1
  456. package/dist/migrate/logto/plugin.d.ts +0 -2
  457. package/dist/migrate/logto/plugin.js +0 -131
  458. package/dist/migrate/logto/plugin.js.map +0 -1
  459. package/dist/migrate/magic/plugin.d.ts +0 -2
  460. package/dist/migrate/magic/plugin.js +0 -56
  461. package/dist/migrate/magic/plugin.js.map +0 -1
  462. package/dist/migrate/nhost/plugin.d.ts +0 -2
  463. package/dist/migrate/nhost/plugin.js +0 -115
  464. package/dist/migrate/nhost/plugin.js.map +0 -1
  465. package/dist/migrate/oidc/plugin.d.ts +0 -2
  466. package/dist/migrate/oidc/plugin.js +0 -73
  467. package/dist/migrate/oidc/plugin.js.map +0 -1
  468. package/dist/migrate/okta/plugin.d.ts +0 -2
  469. package/dist/migrate/okta/plugin.js +0 -105
  470. package/dist/migrate/okta/plugin.js.map +0 -1
  471. package/dist/migrate/onelogin/plugin.d.ts +0 -2
  472. package/dist/migrate/onelogin/plugin.js +0 -61
  473. package/dist/migrate/onelogin/plugin.js.map +0 -1
  474. package/dist/migrate/ory/plugin.d.ts +0 -2
  475. package/dist/migrate/ory/plugin.js +0 -186
  476. package/dist/migrate/ory/plugin.js.map +0 -1
  477. package/dist/migrate/ping-identity/plugin.d.ts +0 -2
  478. package/dist/migrate/ping-identity/plugin.js +0 -100
  479. package/dist/migrate/ping-identity/plugin.js.map +0 -1
  480. package/dist/migrate/pocketbase/plugin.d.ts +0 -2
  481. package/dist/migrate/pocketbase/plugin.js +0 -99
  482. package/dist/migrate/pocketbase/plugin.js.map +0 -1
  483. package/dist/migrate/propelauth/plugin.d.ts +0 -2
  484. package/dist/migrate/propelauth/plugin.js +0 -65
  485. package/dist/migrate/propelauth/plugin.js.map +0 -1
  486. package/dist/migrate/saml/plugin.d.ts +0 -2
  487. package/dist/migrate/saml/plugin.js +0 -79
  488. package/dist/migrate/saml/plugin.js.map +0 -1
  489. package/dist/migrate/stytch/plugin.d.ts +0 -2
  490. package/dist/migrate/stytch/plugin.js +0 -97
  491. package/dist/migrate/stytch/plugin.js.map +0 -1
  492. package/dist/migrate/supabase/plugin.d.ts +0 -2
  493. package/dist/migrate/supabase/plugin.js +0 -149
  494. package/dist/migrate/supabase/plugin.js.map +0 -1
  495. package/dist/migrate/supertokens/plugin.d.ts +0 -2
  496. package/dist/migrate/supertokens/plugin.js +0 -114
  497. package/dist/migrate/supertokens/plugin.js.map +0 -1
  498. package/dist/migrate/user-table/plugin.d.ts +0 -2
  499. package/dist/migrate/user-table/plugin.js +0 -62
  500. package/dist/migrate/user-table/plugin.js.map +0 -1
  501. package/dist/migrate/userfront/plugin.d.ts +0 -2
  502. package/dist/migrate/userfront/plugin.js +0 -60
  503. package/dist/migrate/userfront/plugin.js.map +0 -1
  504. package/dist/migrate/workos/plugin.d.ts +0 -2
  505. package/dist/migrate/workos/plugin.js +0 -81
  506. package/dist/migrate/workos/plugin.js.map +0 -1
  507. package/dist/migrate/zitadel/plugin.d.ts +0 -2
  508. package/dist/migrate/zitadel/plugin.js +0 -114
  509. package/dist/migrate/zitadel/plugin.js.map +0 -1
  510. package/dist/output.d.ts +0 -41
  511. package/dist/output.js +0 -72
  512. package/dist/output.js.map +0 -1
  513. package/dist/project.d.ts +0 -64
  514. package/dist/project.js +0 -86
  515. package/dist/project.js.map +0 -1
  516. package/dist/prompt.d.ts +0 -15
  517. package/dist/prompt.js +0 -46
  518. package/dist/prompt.js.map +0 -1
  519. package/dist/run.d.ts +0 -12
  520. package/dist/run.js +0 -157
  521. package/dist/run.js.map +0 -1
  522. package/dist/secrets.d.ts +0 -41
  523. package/dist/secrets.js +0 -142
  524. package/dist/secrets.js.map +0 -1
  525. package/dist/serialize.d.ts +0 -30
  526. package/dist/serialize.js +0 -131
  527. package/dist/serialize.js.map +0 -1
  528. package/dist/version.d.ts +0 -7
  529. package/dist/version.js +0 -21
  530. package/dist/version.js.map +0 -1
@@ -1,878 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readKeycloakExport = readKeycloakExport;
4
- exports.keycloakBase = keycloakBase;
5
- exports.keycloakAdminHttp = keycloakAdminHttp;
6
- exports.fetchKeycloakRealm = fetchKeycloakRealm;
7
- exports.mapKeycloak = mapKeycloak;
8
- exports.mapKeycloakUser = mapKeycloakUser;
9
- exports.keycloakPassword = keycloakPassword;
10
- exports.keycloakOtp = keycloakOtp;
11
- exports.keycloakRecoveryCodes = keycloakRecoveryCodes;
12
- exports.keycloakPasskey = keycloakPasskey;
13
- exports.isBuiltInRole = isBuiltInRole;
14
- exports.isBuiltInClient = isBuiltInClient;
15
- exports.clientRoleKey = clientRoleKey;
16
- exports.groupKey = groupKey;
17
- exports.base32 = base32;
18
- exports.base64url = base64url;
19
- exports.exportKeycloak = exportKeycloak;
20
- const record_set_1 = require("./record-set");
21
- const translate_kit_1 = require("./translate-kit");
22
- const vendor_http_1 = require("./vendor-http");
23
- /** Realm roles every realm has; never imported as app roles. */
24
- const BUILT_IN_ROLES = new Set(['offline_access', 'uma_authorization']);
25
- /** Clients every realm has (their roles are Keycloak's own admin and account permissions). */
26
- const BUILT_IN_CLIENTS = new Set(['account', 'account-console', 'admin-cli', 'broker', 'realm-management', 'security-admin-console']);
27
- /** Brokered identity providers that are enterprise connections, not social sign-in. */
28
- const ENTERPRISE = new Set(['saml', 'oidc', 'keycloak-oidc']);
29
- /** Keycloak social provider ids that `socialKey` does not already know. */
30
- const KC_SOCIAL = { 'linkedin-openid-connect': 'linkedin' };
31
- /** User attributes the user record carries itself. */
32
- const PHONE_ATTRS = ['phoneNumber', 'phone_number', 'phone', 'mobile'];
33
- const CONSUMED_ATTRS = new Set([...PHONE_ATTRS, 'phoneNumberVerified', 'phone_number_verified', 'picture']);
34
- // ── reading a realm export ──────────────────────────────────────────────────
35
- /**
36
- * Assemble a snapshot from the JSON documents of a realm export: one realm
37
- * file (`--file`, a realm object or an array of realms), or a `--dir` export
38
- * (`<realm>-realm.json` plus `<realm>-users-<n>.json` / `<realm>-federated-users-<n>.json`
39
- * chunks, each `{ realm, users }`). `realmName` picks a realm when there are several.
40
- */
41
- function readKeycloakExport(docs, realmName) {
42
- const realms = [];
43
- const chunks = [];
44
- for (const doc of docs) {
45
- for (const d of Array.isArray(doc) ? doc.filter(record_set_1.isObj) : (0, record_set_1.isObj)(doc) ? [doc] : []) {
46
- // A users chunk carries only `realm` (the name) and the user lists.
47
- if (typeof d.realm === 'string' && Object.keys(d).every((k) => ['realm', 'users', 'federatedUsers'].includes(k)))
48
- chunks.push(d);
49
- else if (typeof d.realm === 'string')
50
- realms.push(d);
51
- }
52
- }
53
- if (!realms.length)
54
- throw new Error('No realm found in the Keycloak export (expected the JSON written by kc.sh export).');
55
- let realm;
56
- if (realmName)
57
- realm = realms.find((r) => r.realm === realmName);
58
- else if (realms.length === 1)
59
- realm = realms[0];
60
- else {
61
- // A full-server export also holds master: the one other realm is the app's.
62
- const apps = realms.filter((r) => r.realm !== 'master');
63
- if (apps.length === 1)
64
- realm = apps[0];
65
- }
66
- if (!realm) {
67
- throw new Error(realmName
68
- ? `Realm "${realmName}" is not in the export (found: ${realms.map((r) => String(r.realm)).join(', ')}).`
69
- : `The export holds several realms (${realms.map((r) => String(r.realm)).join(', ')}): name one with --set keycloak-realm=<realm>.`);
70
- }
71
- const name = String(realm.realm);
72
- const mine = chunks.filter((c) => c.realm === name);
73
- const { users, federatedUsers, ...rest } = realm;
74
- return {
75
- realm: rest,
76
- users: [...(0, record_set_1.objs)(users), ...mine.flatMap((c) => (0, record_set_1.objs)(c.users))],
77
- federatedUsers: [...(0, record_set_1.objs)(federatedUsers), ...mine.flatMap((c) => (0, record_set_1.objs)(c.federatedUsers))],
78
- groups: (0, record_set_1.objs)(realm.groups),
79
- organizations: (0, record_set_1.objs)(realm.organizations),
80
- invitations: [],
81
- source: 'file',
82
- };
83
- }
84
- /** `https://sso.example.com/` → `https://sso.example.com`; a bare host gets https. */
85
- function keycloakBase(raw) {
86
- const s = raw.trim().replace(/\/+$/, '');
87
- return /^https?:\/\//.test(s) ? s : `https://${s}`;
88
- }
89
- /**
90
- * The Admin REST API (`{base}/admin/realms`) with an admin access token, fetched
91
- * on first use and again shortly before it expires. Paths start with `/<realm>`.
92
- */
93
- function keycloakAdminHttp(o) {
94
- const base = keycloakBase(o.baseUrl);
95
- const fetchImpl = o.fetchImpl ?? fetch;
96
- const now = o.now ?? Date.now;
97
- const byUser = !!(o.username && o.password);
98
- if (!byUser && !(o.clientId && o.clientSecret))
99
- throw new Error('Keycloak Admin API needs an admin client (client id + secret) or an admin user (username + password).');
100
- const authRealm = o.authRealm ?? (byUser ? 'master' : o.realm);
101
- const tokenPath = `/realms/${encodeURIComponent(authRealm)}/protocol/openid-connect/token`;
102
- let cached = null;
103
- const token = async () => {
104
- if (cached && cached.until > now())
105
- return cached.value;
106
- const form = new URLSearchParams(byUser
107
- ? { grant_type: 'password', client_id: o.clientId ?? 'admin-cli', username: o.username, password: o.password }
108
- : { grant_type: 'client_credentials', client_id: o.clientId, client_secret: o.clientSecret });
109
- if (byUser && o.clientSecret)
110
- form.set('client_secret', o.clientSecret);
111
- let res;
112
- try {
113
- res = await fetchImpl(`${base}${tokenPath}`, { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' }, body: form.toString() });
114
- }
115
- catch (err) {
116
- throw new vendor_http_1.VendorApiError('Keycloak', 0, tokenPath, err instanceof Error ? err.message : String(err));
117
- }
118
- const body = (await res.json().catch(() => null));
119
- if (res.status !== 200 || typeof body?.access_token !== 'string') {
120
- const detail = typeof body?.error_description === 'string' ? body.error_description : typeof body?.error === 'string' ? body.error : '';
121
- throw new vendor_http_1.VendorApiError('Keycloak', res.status, tokenPath, detail);
122
- }
123
- const ttl = typeof body.expires_in === 'number' ? body.expires_in : 60;
124
- cached = { value: body.access_token, until: now() + Math.max(ttl - 30, 5) * 1000 };
125
- return cached.value;
126
- };
127
- return new vendor_http_1.VendorHttp({
128
- vendor: 'Keycloak',
129
- baseUrl: `${base}/admin/realms`,
130
- headers: async () => ({ authorization: `Bearer ${await token()}` }),
131
- fetchImpl,
132
- sleep: o.sleep,
133
- now,
134
- });
135
- }
136
- /** Read a realm through the Admin REST API into the realm-export shape. */
137
- async function fetchKeycloakRealm(http, o) {
138
- const r = `/${encodeURIComponent(o.realm)}`;
139
- const max = o.pageSize ?? 100;
140
- const progress = o.onProgress ?? (() => undefined);
141
- const warn = o.warn ?? (() => undefined);
142
- const list = async (path) => (0, record_set_1.objs)((await http.get(path)).body);
143
- /** A listing the token may not be allowed to read, or the server too old to have. */
144
- const optional = async (path, what) => {
145
- try {
146
- return await list(path);
147
- }
148
- catch (err) {
149
- if (!(err instanceof vendor_http_1.VendorApiError) || ![403, 404].includes(err.status))
150
- throw err;
151
- if (err.status === 403)
152
- warn(`${what} could not be read with this admin credential (403) and were skipped.`);
153
- return [];
154
- }
155
- };
156
- const paged = async (path) => {
157
- const out = [];
158
- const sep = path.includes('?') ? '&' : '?';
159
- for (let first = 0;; first += max) {
160
- const page = await list(`${path}${sep}first=${first}&max=${max}`);
161
- out.push(...page);
162
- if (page.length < max)
163
- return out;
164
- }
165
- };
166
- progress('realm');
167
- const realm = (await http.get(r)).body;
168
- if (!(0, record_set_1.isObj)(realm))
169
- throw new Error(`Keycloak returned no realm "${o.realm}".`);
170
- realm.identityProviders = await optional(`${r}/identity-provider/instances`, 'Identity providers');
171
- const clients = await optional(`${r}/clients`, 'Clients');
172
- realm.clients = clients;
173
- const clientRoles = {};
174
- for (const c of clients) {
175
- const clientId = (0, record_set_1.str)(c.clientId);
176
- if (!clientId || !(0, record_set_1.str)(c.id) || isBuiltInClient(clientId, o.realm))
177
- continue;
178
- const roles = await optional(`${r}/clients/${encodeURIComponent((0, record_set_1.str)(c.id))}/roles`, `Roles of client ${clientId}`);
179
- if (roles.length)
180
- clientRoles[clientId] = roles;
181
- }
182
- realm.roles = { realm: await optional(`${r}/roles?briefRepresentation=false`, 'Realm roles'), client: clientRoles };
183
- progress('users');
184
- const groups = new Map();
185
- const users = await paged(`${r}/users?briefRepresentation=false`);
186
- for (const u of users) {
187
- const id = (0, record_set_1.str)(u.id);
188
- if (!id || (0, record_set_1.str)(u.serviceAccountClientId))
189
- continue;
190
- const base = `${r}/users/${encodeURIComponent(id)}`;
191
- u.federatedIdentities = await list(`${base}/federated-identity`);
192
- const memberOf = await list(`${base}/groups?briefRepresentation=false`);
193
- u.groups = memberOf.map((g) => (0, record_set_1.str)(g.path)).filter((p) => !!p);
194
- for (const g of memberOf)
195
- if ((0, record_set_1.str)(g.path))
196
- groups.set((0, record_set_1.str)(g.path), g);
197
- const mappings = (await http.get(`${base}/role-mappings`)).body;
198
- u.realmRoles = (0, record_set_1.objs)((0, record_set_1.isObj)(mappings) ? mappings.realmMappings : undefined).map((m) => (0, record_set_1.str)(m.name)).filter((n) => !!n);
199
- const byClient = {};
200
- for (const [key, m] of Object.entries((0, record_set_1.isObj)(mappings) && (0, record_set_1.isObj)(mappings.clientMappings) ? mappings.clientMappings : {})) {
201
- if (!(0, record_set_1.isObj)(m))
202
- continue;
203
- const names = (0, record_set_1.objs)(m.mappings).map((x) => (0, record_set_1.str)(x.name)).filter((n) => !!n);
204
- if (names.length)
205
- byClient[(0, record_set_1.str)(m.client) ?? key] = names;
206
- }
207
- u.clientRoles = byClient;
208
- u.credentials = await list(`${base}/credentials`);
209
- }
210
- // Roles reach a member through every ancestor group: read the parents nobody is a direct member of.
211
- for (const path of [...groups.keys()]) {
212
- const parts = path.split('/').filter(Boolean);
213
- for (let i = parts.length - 1; i > 0; i--) {
214
- const parent = `/${parts.slice(0, i).join('/')}`;
215
- if (groups.has(parent))
216
- continue;
217
- try {
218
- const { body } = await http.get(`${r}/group-by-path/${parts.slice(0, i).map(encodeURIComponent).join('/')}`);
219
- if ((0, record_set_1.isObj)(body))
220
- groups.set(parent, { ...body, path: parent, subGroups: [] });
221
- }
222
- catch (err) {
223
- if (!(err instanceof vendor_http_1.VendorApiError))
224
- throw err;
225
- }
226
- }
227
- }
228
- const organizations = [];
229
- const invitations = [];
230
- if (realm.organizationsEnabled === true) {
231
- progress('organizations');
232
- for (const org of await optional(`${r}/organizations?briefRepresentation=false&first=0&max=100000`, 'Organizations')) {
233
- const id = (0, record_set_1.str)(org.id);
234
- if (!id)
235
- continue;
236
- const path = `${r}/organizations/${encodeURIComponent(id)}`;
237
- org.members = await paged(`${path}/members`);
238
- organizations.push(org);
239
- // Invitations have an admin endpoint from Keycloak 26.2 on; older servers answer 404.
240
- for (const inv of await optional(`${path}/invitations?first=0&max=100000`, `Invitations of ${(0, record_set_1.str)(org.name) ?? id}`))
241
- invitations.push({ organizationId: id, ...inv });
242
- }
243
- }
244
- return { realm, users, federatedUsers: [], groups: [...groups.values()], organizations, invitations, source: 'api', baseUrl: o.baseUrl ? keycloakBase(o.baseUrl) : undefined };
245
- }
246
- // ── mapping ─────────────────────────────────────────────────────────────────
247
- /** Map a snapshot (realm export or API) onto canonical records. */
248
- function mapKeycloak(snap, opts = {}) {
249
- const set = new record_set_1.RecordSet();
250
- const realm = snap.realm;
251
- const realmName = (0, record_set_1.str)(realm.realm) ?? 'realm';
252
- const groupsAs = opts.groupsAs ?? 'roles';
253
- const groups = indexGroups(snap.groups);
254
- // ── Keycloak organizations (25+) ──
255
- const orgIds = new Set();
256
- const orgOfIdp = new Map();
257
- for (const o of snap.organizations) {
258
- const id = (0, record_set_1.str)(o.id);
259
- const name = (0, record_set_1.str)(o.name);
260
- if (!id || !name)
261
- continue;
262
- orgIds.add(id);
263
- for (const idp of (0, record_set_1.objs)(o.identityProviders))
264
- if ((0, record_set_1.str)(idp.alias))
265
- orgOfIdp.set((0, record_set_1.str)(idp.alias), id);
266
- set.add('organization', (0, record_set_1.compact)({
267
- id,
268
- name,
269
- slug: (0, record_set_1.str)(o.alias),
270
- domains: (0, record_set_1.objs)(o.domains).map((d) => (0, record_set_1.str)(d.name)?.toLowerCase()).filter((d) => !!d),
271
- public_metadata: (0, record_set_1.bag)((0, record_set_1.compact)({ description: (0, record_set_1.str)(o.description), redirect_url: (0, record_set_1.str)(o.redirectUrl), ...unwrapAttributes(o.attributes) })),
272
- private_metadata: o.enabled === false ? { keycloak_enabled: false } : undefined,
273
- }));
274
- }
275
- if (orgIds.size)
276
- set.add('role', { key: 'member', name: 'Member', scope: 'organization' }, 'org:member');
277
- // ── groups as organizations ──
278
- if (groupsAs === 'organizations') {
279
- for (const g of groups.values()) {
280
- set.add('organization', (0, record_set_1.compact)({ id: g.id, name: g.name, slug: g.path.split('/').filter(Boolean).map((s) => (0, translate_kit_1.keyOf)(s).replace(/_/g, '-')).join('-'), public_metadata: (0, record_set_1.bag)({ keycloak_group_path: g.path, ...unwrapAttributes(g.attributes) }) }));
281
- }
282
- if (groups.size)
283
- set.add('role', { key: 'member', name: 'Member', scope: 'organization' }, 'org:member');
284
- }
285
- // ── roles: realm roles, client roles, groups ──
286
- const roles = (0, record_set_1.isObj)(realm.roles) ? realm.roles : {};
287
- let composite = false;
288
- for (const role of (0, record_set_1.objs)(roles.realm)) {
289
- const name = (0, record_set_1.str)(role.name);
290
- if (!name || isBuiltInRole(name))
291
- continue;
292
- if (role.composite === true)
293
- composite = true;
294
- set.add('role', (0, record_set_1.compact)({ key: (0, translate_kit_1.keyOf)(name), name, description: (0, record_set_1.str)(role.description), scope: 'app' }), (0, translate_kit_1.keyOf)(name));
295
- }
296
- for (const [clientId, list] of Object.entries((0, record_set_1.isObj)(roles.client) ? roles.client : {})) {
297
- if (isBuiltInClient(clientId, realmName))
298
- continue;
299
- for (const role of (0, record_set_1.objs)(list)) {
300
- const name = (0, record_set_1.str)(role.name);
301
- if (!name)
302
- continue;
303
- if (role.composite === true)
304
- composite = true;
305
- set.add('role', (0, record_set_1.compact)({ key: clientRoleKey(clientId, name), name: `${clientId}: ${name}`, description: (0, record_set_1.str)(role.description), scope: 'app' }), clientRoleKey(clientId, name));
306
- }
307
- }
308
- if (groupsAs === 'roles') {
309
- for (const g of groups.values())
310
- set.add('role', { key: groupKey(g.path), name: g.path, description: 'Keycloak group', scope: 'app' }, groupKey(g.path));
311
- }
312
- if (composite)
313
- set.warn('Composite roles were imported as plain roles: a user holds the roles assigned to them and their groups, not the roles a composite role includes. Assign those in Atlas, or give the composite role the permissions it stood for.');
314
- // ── identity providers ──
315
- const idps = new Map();
316
- for (const idp of (0, record_set_1.objs)(realm.identityProviders))
317
- if ((0, record_set_1.str)(idp.alias))
318
- idps.set((0, record_set_1.str)(idp.alias), idp);
319
- const connections = new Set();
320
- for (const [alias, idp] of idps) {
321
- const providerId = (0, record_set_1.str)(idp.providerId) ?? '';
322
- if (!ENTERPRISE.has(providerId))
323
- continue;
324
- const orgId = (0, record_set_1.str)(idp.organizationId) ?? orgOfIdp.get(alias);
325
- const connection = ssoConnection(idp, {
326
- realm: realmName,
327
- baseUrl: snap.baseUrl,
328
- organizationId: orgId && orgIds.has(orgId) ? orgId : undefined,
329
- domains: [
330
- ...(0, record_set_1.strs)((0, record_set_1.isObj)(idp.config) ? [idp.config['kc.org.domain']] : []),
331
- ...snap.organizations.filter((o) => (0, record_set_1.str)(o.id) === orgId).flatMap((o) => (0, record_set_1.objs)(o.domains).filter((d) => !(0, record_set_1.str)(d.identityProviderAlias) || (0, record_set_1.str)(d.identityProviderAlias) === alias).map((d) => (0, record_set_1.str)(d.name))),
332
- ],
333
- warn: (m) => set.warn(m),
334
- });
335
- set.add('sso_connection', connection);
336
- connections.add(alias);
337
- }
338
- // ── users ──
339
- const rpIds = {
340
- webauthn: (0, record_set_1.str)(realm.webAuthnPolicyRpId) ?? opts.rpId,
341
- passwordless: (0, record_set_1.str)(realm.webAuthnPolicyPasswordlessRpId) ?? (0, record_set_1.str)(realm.webAuthnPolicyRpId) ?? opts.rpId,
342
- };
343
- const userIdByName = new Map();
344
- const counts = { password: 0, federated: 0, otpWithoutSecret: 0, temporary: 0 };
345
- const badHashes = new Map();
346
- for (const u of snap.users) {
347
- if ((0, record_set_1.str)(u.serviceAccountClientId)) {
348
- set.omit('user', 'Keycloak service-account user (a client credential, not a person)');
349
- continue;
350
- }
351
- const user = mapKeycloakUser(u, realm);
352
- if (!user) {
353
- set.omit('user', 'no id, email or username');
354
- continue;
355
- }
356
- const id = user.id;
357
- if ((0, record_set_1.str)(u.username))
358
- userIdByName.set((0, record_set_1.str)(u.username).toLowerCase(), id);
359
- if ((0, record_set_1.str)(u.federationLink))
360
- counts.federated++;
361
- if ((0, record_set_1.strs)(u.requiredActions).includes('UPDATE_PASSWORD'))
362
- counts.temporary++;
363
- const creds = (0, record_set_1.objs)(u.credentials);
364
- // Keycloak lists credentials by priority: the first password is the one it checks.
365
- const pw = creds.find((c) => (0, record_set_1.str)(c.type) === 'password');
366
- if (pw) {
367
- if (snap.source === 'api')
368
- counts.password++;
369
- else {
370
- const r = keycloakPassword(pw);
371
- if ('hash' in r)
372
- user.password = r.hash;
373
- else
374
- badHashes.set(r.problem, (badHashes.get(r.problem) ?? 0) + 1);
375
- }
376
- }
377
- user.roles = userRoleKeys(u, groups, realmName, groupsAs === 'roles');
378
- set.add('user', (0, record_set_1.compact)(user));
379
- for (const fi of (0, record_set_1.objs)(u.federatedIdentities)) {
380
- const identity = mapFederatedIdentity(fi, id, idps, connections);
381
- if (identity)
382
- set.add('identity', identity, `${identity.provider}:${identity.provider_user_id}`);
383
- }
384
- let hasOtp = false;
385
- for (const c of creds) {
386
- const type = (0, record_set_1.str)(c.type) ?? '';
387
- if (type === 'otp' || type === 'totp' || type === 'hotp') {
388
- hasOtp = true;
389
- if (snap.source === 'api')
390
- continue;
391
- const f = keycloakOtp(c);
392
- if ('factor' in f)
393
- set.add('mfa_factor', { user_id: id, ...f.factor }, `otp:${id}:${(0, record_set_1.str)(c.id) ?? set.count('mfa_factor')}`);
394
- else
395
- set.omit('mfa_factor', f.problem);
396
- }
397
- else if (type === 'recovery-authn-codes') {
398
- if (snap.source === 'api') {
399
- set.omit('mfa_factor', 'recovery codes: the Admin API does not return their hashes (use a realm export)');
400
- continue;
401
- }
402
- const f = keycloakRecoveryCodes(c);
403
- if (f)
404
- set.add('mfa_factor', { user_id: id, ...f }, `recovery:${id}`);
405
- else
406
- set.omit('mfa_factor', 'recovery codes: none left');
407
- }
408
- else if (type === 'webauthn' || type === 'webauthn-passwordless') {
409
- const rp = type === 'webauthn' ? rpIds.webauthn : rpIds.passwordless;
410
- const p = keycloakPasskey(c, rp);
411
- if ('passkey' in p)
412
- set.add('passkey', { user_id: id, ...p.passkey }, `passkey:${p.passkey.credential_id}`);
413
- else
414
- set.omit('passkey', p.problem);
415
- }
416
- }
417
- if (hasOtp && snap.source === 'api')
418
- counts.otpWithoutSecret++;
419
- else if (u.totp === true && !hasOtp && snap.source === 'api')
420
- counts.otpWithoutSecret++;
421
- if (groupsAs === 'organizations') {
422
- for (const path of (0, record_set_1.strs)(u.groups)) {
423
- const g = groups.get(path);
424
- if (g)
425
- set.add('membership', { organization_id: g.id, user_id: id, role: 'member' }, `${g.id}:${id}`);
426
- }
427
- }
428
- }
429
- // ── organization members and invitations ──
430
- for (const o of snap.organizations) {
431
- const orgId = (0, record_set_1.str)(o.id);
432
- if (!orgId || !orgIds.has(orgId))
433
- continue;
434
- for (const m of (0, record_set_1.objs)(o.members)) {
435
- const uid = (0, record_set_1.str)(m.id) ?? ((0, record_set_1.str)(m.username) ? userIdByName.get((0, record_set_1.str)(m.username).toLowerCase()) : undefined);
436
- if (!uid) {
437
- set.omit('membership', 'organization member not among the exported users');
438
- continue;
439
- }
440
- set.add('membership', { organization_id: orgId, user_id: uid, role: 'member' }, `${orgId}:${uid}`);
441
- }
442
- }
443
- for (const inv of snap.invitations) {
444
- const id = (0, record_set_1.str)(inv.id);
445
- const email = (0, record_set_1.str)(inv.email)?.toLowerCase();
446
- const orgId = (0, record_set_1.str)(inv.organizationId);
447
- if (!id || !email)
448
- continue;
449
- const status = (0, record_set_1.str)(inv.status)?.toUpperCase();
450
- set.add('invitation', (0, record_set_1.compact)({
451
- id,
452
- organization_id: orgId && orgIds.has(orgId) ? orgId : undefined,
453
- email,
454
- role: 'member',
455
- status: status === 'EXPIRED' ? 'expired' : 'pending',
456
- // Keycloak keeps these as epoch seconds.
457
- expires_at: typeof inv.expiresAt === 'number' && inv.expiresAt > 0 ? inv.expiresAt * 1000 : undefined,
458
- created_at: typeof inv.sentDate === 'number' && inv.sentDate > 0 ? inv.sentDate * 1000 : undefined,
459
- }));
460
- }
461
- if (snap.federatedUsers.length)
462
- set.omit('user', 'kept by a user-storage provider without import (no local profile): they move by lazy migration through Keycloak', snap.federatedUsers.length);
463
- // ── what could not move, in plain words ──
464
- if (counts.password) {
465
- set.warn(`${counts.password} user(s) have a Keycloak password, but the Admin API never returns password hashes. Export the realm with kc.sh export (the only path that carries hashes) or turn on the keycloak lazy-migration preset: each password is then checked against Keycloak on its first Atlas sign-in.`);
466
- }
467
- if (counts.otpWithoutSecret) {
468
- set.warn(`${counts.otpWithoutSecret} user(s) use an authenticator app; the Admin API does not return OTP secrets. A realm export (kc.sh export) carries them; otherwise those users enrol again in Atlas.`);
469
- }
470
- if (counts.federated) {
471
- set.warn(`${counts.federated} user(s) are federated from LDAP / Kerberos (federationLink): Keycloak stores no password for them. Use the keycloak lazy-migration preset (Keycloak checks the password against the directory).`);
472
- }
473
- if (counts.temporary)
474
- set.warn(`${counts.temporary} user(s) must change their password at their next Keycloak sign-in (UPDATE_PASSWORD): their current password was set by an administrator.`);
475
- for (const [problem, n] of badHashes)
476
- set.warn(`${n} user(s) were imported without a password (${problem}); they reset it, or use lazy migration.`);
477
- if (snap.users.some((u) => (0, record_set_1.objs)(u.credentials).some((c) => (0, record_set_1.str)(c.type)?.startsWith('webauthn'))) && !rpIds.passwordless && !rpIds.webauthn) {
478
- set.warn('The realm sets no WebAuthn relying-party id (Keycloak then uses its own host name): pass --set keycloak-rp-id=<host> to carry passkeys.');
479
- }
480
- set.warn('Keycloak sessions are not exportable: the keycloak bridge preset exchanges Keycloak access and ID tokens for Atlas sessions instead.');
481
- const otpAlgorithm = (0, record_set_1.str)(realm.otpPolicyAlgorithm);
482
- set.manifest = {
483
- origin: snap.baseUrl ? `${snap.baseUrl}/realms/${realmName}` : `realm ${realmName}`,
484
- sourceVersion: (0, record_set_1.str)(realm.keycloakVersion) ?? null,
485
- rpId: rpIds.passwordless ?? rpIds.webauthn ?? null,
486
- providers: [...new Set(set.list('identity').map((i) => i.provider))].sort(),
487
- settings: (0, record_set_1.compact)({
488
- realm: realmName,
489
- source: snap.source === 'file' ? 'realm_export' : 'admin_api',
490
- groups_as: groupsAs,
491
- password_policy: (0, record_set_1.str)(realm.passwordPolicy),
492
- otp: (0, record_set_1.str)(realm.otpPolicyType)
493
- ? { type: (0, record_set_1.str)(realm.otpPolicyType), algorithm: otpAlgorithm ? otpAlgorithmOf(otpAlgorithm) : 'SHA1', digits: realm.otpPolicyDigits ?? 6, period: realm.otpPolicyPeriod ?? 30 }
494
- : undefined,
495
- }),
496
- };
497
- return set;
498
- }
499
- /** One Keycloak user → a user record without password and roles (null when it has nothing to sign in with). */
500
- function mapKeycloakUser(u, realm = {}) {
501
- const id = (0, record_set_1.str)(u.id);
502
- if (!id)
503
- return null;
504
- const email = (0, record_set_1.str)(u.email)?.toLowerCase();
505
- const username = (0, record_set_1.str)(u.username)?.toLowerCase();
506
- const attrs = unwrapAttributes(u.attributes);
507
- const phoneRaw = PHONE_ATTRS.map((k) => attrs[k]).find((v) => typeof v === 'string');
508
- const phone = (0, record_set_1.e164)(phoneRaw);
509
- const phoneVerified = attrs.phoneNumberVerified === 'true' || attrs.phone_number_verified === 'true';
510
- const custom = Object.fromEntries(Object.entries(attrs).filter(([k]) => !CONSUMED_ATTRS.has(k)));
511
- const actions = (0, record_set_1.strs)(u.requiredActions);
512
- const user = (0, record_set_1.compact)({
513
- id,
514
- emails: email ? [{ email, verified: u.emailVerified === true, primary: true }] : [],
515
- phones: phone ? [{ phone, verified: phoneVerified, primary: !email }] : [],
516
- // With "email as username" the username is the address: keep it only when it is a real username.
517
- username: username && username !== email && realm.registrationEmailAsUsername !== true ? username : undefined,
518
- first_name: (0, record_set_1.str)(u.firstName),
519
- last_name: (0, record_set_1.str)(u.lastName),
520
- image_url: typeof attrs.picture === 'string' && /^https:\/\//.test(attrs.picture) ? attrs.picture : undefined,
521
- banned: u.enabled === false ? true : undefined,
522
- ban_reason: u.enabled === false ? 'Disabled in Keycloak' : undefined,
523
- private_metadata: (0, record_set_1.bag)({
524
- ...custom,
525
- ...(actions.length ? { keycloak_required_actions: actions } : {}),
526
- ...((0, record_set_1.str)(u.federationLink) ? { keycloak_federation_link: (0, record_set_1.str)(u.federationLink) } : {}),
527
- }),
528
- created_at: typeof u.createdTimestamp === 'number' ? u.createdTimestamp : undefined,
529
- });
530
- return user.emails?.length || user.phones?.length || user.username ? user : null;
531
- }
532
- // ── credentials ─────────────────────────────────────────────────────────────
533
- /** PBKDF2 provider ids → digest (`pbkdf2` is PBKDF2WithHmacSHA1). */
534
- const PBKDF2 = { pbkdf2: 'sha1', 'pbkdf2-sha1': 'sha1', 'pbkdf2-sha256': 'sha256', 'pbkdf2-sha512': 'sha512' };
535
- /** Keycloak's Argon2 version names → the PHC `v=` value. */
536
- const ARGON2_VERSIONS = { '1.3': 19, '1.0': 16 };
537
- /**
538
- * A Keycloak password credential → an Atlas password hash. Keycloak 9+ keeps
539
- * `secretData` `{ value, salt }` and `credentialData` `{ algorithm,
540
- * hashIterations, additionalParameters }` as JSON strings; earlier exports
541
- * (and hand-written import files) put `hashedSaltedValue`, `salt`,
542
- * `hashIterations` and `algorithm` on the credential itself. Salts and values
543
- * are standard base64.
544
- */
545
- function keycloakPassword(cred) {
546
- const secret = jsonObj(cred.secretData);
547
- const data = jsonObj(cred.credentialData);
548
- const value = (0, record_set_1.str)(secret.value) ?? (0, record_set_1.str)(cred.hashedSaltedValue);
549
- const salt = (0, record_set_1.str)(secret.salt) ?? (0, record_set_1.str)(cred.salt);
550
- const algorithm = ((0, record_set_1.str)(data.algorithm) ?? (0, record_set_1.str)(cred.algorithm))?.toLowerCase();
551
- const iterations = Number(data.hashIterations ?? cred.hashIterations);
552
- if (!value)
553
- return { problem: 'no stored password value' };
554
- // Community bcrypt providers store the whole digest as the value.
555
- if (/^\$2[aby]\$\d{2}\$/.test(value))
556
- return { hash: { algorithm: 'bcrypt', hash: value } };
557
- if (!algorithm)
558
- return { problem: 'the password credential names no algorithm' };
559
- const digest = PBKDF2[algorithm];
560
- if (digest) {
561
- if (!salt || !Number.isInteger(iterations) || iterations < 1)
562
- return { problem: `${algorithm} without a salt or iteration count` };
563
- // PBEKeySpec over the password's UTF-8 bytes; the key length is the decoded value's (512 bits, or 256 for pbkdf2-sha256 from Keycloak 24 on).
564
- return { hash: { algorithm: 'pbkdf2', hash: value, salt, params: { digest, iterations, encoding: 'base64', salt_encoding: 'base64' } } };
565
- }
566
- if (algorithm === 'argon2') {
567
- const extra = (0, record_set_1.isObj)(data.additionalParameters) ? data.additionalParameters : {};
568
- const first = (k) => (0, record_set_1.str)(Array.isArray(extra[k]) ? extra[k][0] : extra[k]);
569
- const type = first('type') ?? 'id';
570
- const version = ARGON2_VERSIONS[first('version') ?? '1.3'];
571
- const memory = Number(first('memory') ?? 7168);
572
- const parallelism = Number(first('parallelism') ?? 1);
573
- const t = Number.isInteger(iterations) && iterations > 0 ? iterations : 5;
574
- if (!salt || !['id', 'i', 'd'].includes(type) || version === undefined || !Number.isInteger(memory) || !Number.isInteger(parallelism)) {
575
- return { problem: 'an Argon2 credential with parameters Keycloak never writes' };
576
- }
577
- // Keycloak's Argon2PasswordHashProvider (BouncyCastle, UTF-8 password) as the
578
- // PHC string the reference argon2 tool prints for the same inputs.
579
- const nopad = (s) => s.replace(/=+$/, '');
580
- return { hash: { algorithm: 'argon2', hash: `$argon2${type}$v=${version}$m=${memory},t=${t},p=${parallelism}$${nopad(salt)}$${nopad(value)}` } };
581
- }
582
- return { problem: `unsupported hash algorithm "${algorithm}"` };
583
- }
584
- /**
585
- * A Keycloak OTP credential → a TOTP factor. The secret is a plain string whose
586
- * UTF-8 BYTES are the HMAC key (OTPCredentialModel.getDecodedSecret); Keycloak
587
- * shows their base32 in the QR code. With `secretEncoding: "BASE32"` (secrets
588
- * imported from elsewhere) the value already is base32.
589
- */
590
- function keycloakOtp(cred) {
591
- const secret = jsonObj(cred.secretData);
592
- const data = jsonObj(cred.credentialData);
593
- const raw = typeof secret.value === 'string' && secret.value ? secret.value : typeof cred.value === 'string' && cred.value ? cred.value : undefined;
594
- const subType = ((0, record_set_1.str)(data.subType) ?? ((0, record_set_1.str)(cred.type) === 'hotp' ? 'hotp' : 'totp')).toLowerCase();
595
- if (subType === 'hotp')
596
- return { problem: 'HOTP (counter-based) authenticators have no Atlas counterpart; re-enrol in Atlas' };
597
- if (!raw)
598
- return { problem: 'OTP credential without its secret' };
599
- const encoding = (0, record_set_1.str)(data.secretEncoding)?.toUpperCase();
600
- const secretBase32 = encoding === 'BASE32' ? raw.toUpperCase().replace(/[\s=]/g, '') : base32(Buffer.from(raw, 'utf8'));
601
- const digits = Number(data.digits ?? cred.digits ?? 6);
602
- const period = Number(data.period ?? cred.period ?? 30);
603
- return {
604
- factor: (0, record_set_1.compact)({
605
- type: 'totp',
606
- secret_base32: secretBase32,
607
- digits: Number.isInteger(digits) && digits > 0 ? digits : 6,
608
- period: Number.isInteger(period) && period > 0 ? period : 30,
609
- algorithm: otpAlgorithmOf((0, record_set_1.str)(data.algorithm) ?? (0, record_set_1.str)(cred.algorithm) ?? 'HmacSHA1'),
610
- verified: true,
611
- created_at: typeof cred.createdDate === 'number' ? cred.createdDate : undefined,
612
- }),
613
- };
614
- }
615
- /**
616
- * Recovery codes (`recovery-authn-codes`): Keycloak keeps base64 SHA-512 of
617
- * each remaining code (RecoveryAuthnCodesUtils.hashRawCode), in the order the
618
- * user must use them; Atlas accepts any remaining one.
619
- */
620
- function keycloakRecoveryCodes(cred) {
621
- const codes = (0, record_set_1.objs)(jsonObj(cred.secretData).codes)
622
- .map((c) => (0, record_set_1.str)(c.encodedHashedValue))
623
- .filter((h) => !!h);
624
- if (!codes.length)
625
- return null;
626
- return (0, record_set_1.compact)({
627
- type: 'backup_codes',
628
- backup_code_hashes: codes.map((hash) => ({ algorithm: 'sha512', hash, params: { encoding: 'base64' } })),
629
- verified: true,
630
- created_at: typeof cred.createdDate === 'number' ? cred.createdDate : undefined,
631
- });
632
- }
633
- /**
634
- * A WebAuthn credential (`webauthn` second factor or `webauthn-passwordless`
635
- * passkey). `credentialId` is standard base64 and `credentialPublicKey` the
636
- * base64url COSE key (CredentialPublicKeyConverter); both become base64url.
637
- */
638
- function keycloakPasskey(cred, rpId) {
639
- const data = jsonObj(cred.credentialData);
640
- const credentialId = (0, record_set_1.str)(data.credentialId);
641
- const publicKey = (0, record_set_1.str)(data.credentialPublicKey);
642
- if (!credentialId || !publicKey)
643
- return { problem: 'WebAuthn credential without its id or public key' };
644
- if (!rpId)
645
- return { problem: 'WebAuthn credential with no relying-party id (pass --set keycloak-rp-id=<host>)' };
646
- const aaguid = (0, record_set_1.str)(data.aaguid);
647
- const counter = Number(data.counter);
648
- return {
649
- passkey: (0, record_set_1.compact)({
650
- credential_id: base64url(credentialId),
651
- public_key: base64url(publicKey),
652
- sign_count: Number.isInteger(counter) && counter >= 0 ? counter : undefined,
653
- rp_id: rpId,
654
- transports: (0, record_set_1.strs)(data.transports).sort(),
655
- aaguid: aaguid && aaguid !== '00000000-0000-0000-0000-000000000000' ? aaguid : undefined,
656
- name: (0, record_set_1.str)(cred.userLabel),
657
- created_at: typeof cred.createdDate === 'number' ? cred.createdDate : undefined,
658
- }),
659
- };
660
- }
661
- // ── identities and connections ──────────────────────────────────────────────
662
- function mapFederatedIdentity(fi, userId, idps, connections) {
663
- const alias = (0, record_set_1.str)(fi.identityProvider);
664
- const subject = (0, record_set_1.str)(fi.userId);
665
- if (!alias || !subject)
666
- return null;
667
- const idp = idps.get(alias);
668
- const providerId = (0, record_set_1.str)(idp?.providerId) ?? alias;
669
- const userName = (0, record_set_1.str)(fi.userName);
670
- const email = userName?.includes('@') ? userName.toLowerCase() : undefined;
671
- if (connections.has(alias)) {
672
- return (0, record_set_1.compact)({ user_id: userId, provider: alias, provider_user_id: subject, kind: providerId === 'saml' ? 'saml' : 'oidc', sso_connection_id: alias, email, profile: (0, record_set_1.bag)((0, record_set_1.compact)({ username: userName })) });
673
- }
674
- const provider = KC_SOCIAL[providerId] ?? (0, translate_kit_1.socialKey)(providerId) ?? alias;
675
- return (0, record_set_1.compact)({
676
- user_id: userId,
677
- provider,
678
- provider_user_id: subject,
679
- kind: idp ? 'oauth' : undefined,
680
- email,
681
- profile: (0, record_set_1.bag)((0, record_set_1.compact)({ username: userName, keycloak_alias: alias !== provider ? alias : undefined })),
682
- });
683
- }
684
- function ssoConnection(idp, o) {
685
- const alias = (0, record_set_1.str)(idp.alias);
686
- const name = (0, record_set_1.str)(idp.displayName) ?? alias;
687
- const config = (0, record_set_1.isObj)(idp.config) ? idp.config : {};
688
- const domains = [...new Set(o.domains.filter((d) => !!d).map((d) => d.toLowerCase()))];
689
- const realmUrl = o.baseUrl ? `${o.baseUrl}/realms/${o.realm}` : undefined;
690
- if ((0, record_set_1.str)(idp.providerId) === 'saml') {
691
- const certs = ((0, record_set_1.str)(config.signingCertificate) ?? '').split(',').map((c) => c.trim()).filter(Boolean);
692
- if (certs.length > 1)
693
- o.warn(`SAML identity provider ${name}: it has ${certs.length} signing certificates; the first was imported, add the others in Atlas.`);
694
- return (0, record_set_1.compact)({
695
- id: alias,
696
- name,
697
- organization_id: o.organizationId,
698
- protocol: 'saml',
699
- domains,
700
- enabled: idp.enabled !== false,
701
- saml: (0, record_set_1.compact)({
702
- idp_entity_id: (0, record_set_1.str)(config.idpEntityId),
703
- idp_sso_url: (0, record_set_1.str)(config.singleSignOnServiceUrl),
704
- idp_certificate: certs[0] ? pem(certs[0]) : undefined,
705
- idp_metadata_url: (0, record_set_1.str)(config.metadataDescriptorUrl),
706
- // The IdP knows Keycloak by these: they change to Atlas's values at cutover.
707
- sp_entity_id: (0, record_set_1.str)(config.entityId) ?? realmUrl,
708
- sp_acs_url: realmUrl ? `${realmUrl}/broker/${alias}/endpoint` : undefined,
709
- }),
710
- });
711
- }
712
- const secret = (0, record_set_1.str)(config.clientSecret);
713
- // The Admin API masks secrets; a realm export keeps them, unless they live in a vault.
714
- const realSecret = secret && !/^\*+$/.test(secret) && !secret.startsWith('${vault.') ? secret : undefined;
715
- if (!realSecret)
716
- o.warn(`OIDC identity provider ${name}: its client secret was not available (masked or in a vault); enter it on the SSO connection after the import.`);
717
- const issuer = (0, record_set_1.str)(config.issuer);
718
- return (0, record_set_1.compact)({
719
- id: alias,
720
- name,
721
- organization_id: o.organizationId,
722
- protocol: 'oidc',
723
- domains,
724
- enabled: idp.enabled !== false,
725
- oidc: (0, record_set_1.compact)({
726
- issuer,
727
- discovery_url: (0, record_set_1.str)(config.metadataDescriptorUrl) ?? (issuer ? `${issuer.replace(/\/+$/, '')}/.well-known/openid-configuration` : undefined),
728
- client_id: (0, record_set_1.str)(config.clientId),
729
- client_secret: realSecret,
730
- scopes: ((0, record_set_1.str)(config.defaultScope) ?? '').split(/[\s,]+/).filter(Boolean),
731
- }),
732
- });
733
- }
734
- /** Flatten a group tree (or a flat list) by path. */
735
- function indexGroups(groups, parent = '', out = new Map()) {
736
- for (const g of groups) {
737
- const name = (0, record_set_1.str)(g.name);
738
- if (!name)
739
- continue;
740
- const path = (0, record_set_1.str)(g.path) ?? `${parent}/${name}`;
741
- const clientRoles = {};
742
- for (const [client, list] of Object.entries((0, record_set_1.isObj)(g.clientRoles) ? g.clientRoles : {}))
743
- clientRoles[client] = (0, record_set_1.strs)(list);
744
- out.set(path, { id: (0, record_set_1.str)(g.id) ?? path, name, path, realmRoles: (0, record_set_1.strs)(g.realmRoles), clientRoles, attributes: g.attributes });
745
- indexGroups((0, record_set_1.objs)(g.subGroups), path, out);
746
- }
747
- return out;
748
- }
749
- /**
750
- * A user's app-role keys: realm and client roles mapped to the user, plus the
751
- * roles of every group they belong to and of that group's ancestors (Keycloak
752
- * hands a member all of those), plus one role per group with groups-as-roles.
753
- */
754
- function userRoleKeys(u, groups, realm, groupRoles) {
755
- const keys = new Set();
756
- const addRealm = (name) => {
757
- if (!isBuiltInRole(name))
758
- keys.add((0, translate_kit_1.keyOf)(name));
759
- };
760
- const addClient = (client, names) => {
761
- if (isBuiltInClient(client, realm))
762
- return;
763
- for (const n of names)
764
- keys.add(clientRoleKey(client, n));
765
- };
766
- (0, record_set_1.strs)(u.realmRoles).forEach(addRealm);
767
- for (const [client, names] of Object.entries((0, record_set_1.isObj)(u.clientRoles) ? u.clientRoles : {}))
768
- addClient(client, (0, record_set_1.strs)(names));
769
- for (const path of (0, record_set_1.strs)(u.groups)) {
770
- if (groupRoles)
771
- keys.add(groupKey(path));
772
- const parts = path.split('/').filter(Boolean);
773
- for (let i = 1; i <= parts.length; i++) {
774
- const g = groups.get(`/${parts.slice(0, i).join('/')}`);
775
- if (!g)
776
- continue;
777
- g.realmRoles.forEach(addRealm);
778
- for (const [client, names] of Object.entries(g.clientRoles))
779
- addClient(client, names);
780
- }
781
- }
782
- return [...keys];
783
- }
784
- function isBuiltInRole(name) {
785
- return BUILT_IN_ROLES.has(name) || name.startsWith('default-roles-');
786
- }
787
- function isBuiltInClient(clientId, realm) {
788
- // The master realm has one `<realm>-realm` admin client per realm.
789
- return BUILT_IN_CLIENTS.has(clientId) || (realm === 'master' && clientId.endsWith('-realm'));
790
- }
791
- /** `acme-web` + `billing` → `acme_web:billing`. */
792
- function clientRoleKey(clientId, role) {
793
- return `${(0, translate_kit_1.keyOf)(clientId)}:${(0, translate_kit_1.keyOf)(role)}`;
794
- }
795
- /** `/Engineering/Backend` → `group:engineering_backend`. */
796
- function groupKey(path) {
797
- return `group:${(0, translate_kit_1.keyOf)(path.split('/').filter(Boolean).join('_'))}`;
798
- }
799
- // ── small helpers ───────────────────────────────────────────────────────────
800
- /** Keycloak keeps credential data as JSON strings inside the JSON. */
801
- function jsonObj(v) {
802
- if ((0, record_set_1.isObj)(v))
803
- return v;
804
- if (typeof v !== 'string' || !v.trim())
805
- return {};
806
- try {
807
- const parsed = JSON.parse(v);
808
- return (0, record_set_1.isObj)(parsed) ? parsed : {};
809
- }
810
- catch {
811
- return {};
812
- }
813
- }
814
- /** `{ dept: ["R&D"], tags: ["a", "b"] }` → `{ dept: "R&D", tags: ["a", "b"] }`. */
815
- function unwrapAttributes(v) {
816
- const out = {};
817
- for (const [k, raw] of Object.entries((0, record_set_1.isObj)(v) ? v : {})) {
818
- const list = Array.isArray(raw) ? raw.filter((x) => x !== null && x !== undefined && x !== '') : raw === null || raw === undefined || raw === '' ? [] : [raw];
819
- if (list.length === 1)
820
- out[k] = list[0];
821
- else if (list.length > 1)
822
- out[k] = list;
823
- }
824
- return out;
825
- }
826
- const OTP_ALGORITHMS = { hmacsha1: 'SHA1', hmacsha256: 'SHA256', hmacsha512: 'SHA512', sha1: 'SHA1', sha256: 'SHA256', sha512: 'SHA512' };
827
- /** `HmacSHA256` → `SHA256` (SHA1 for anything unknown, Keycloak's default). */
828
- function otpAlgorithmOf(raw) {
829
- return OTP_ALGORITHMS[raw.toLowerCase().replace(/[^a-z0-9]/g, '')] ?? 'SHA1';
830
- }
831
- const B32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
832
- /** RFC 4648 base32, upper case, no padding. */
833
- function base32(bytes) {
834
- let out = '';
835
- let bits = 0;
836
- let value = 0;
837
- for (const b of bytes) {
838
- value = (value << 8) | b;
839
- bits += 8;
840
- while (bits >= 5) {
841
- out += B32.charAt((value >>> (bits - 5)) & 31);
842
- bits -= 5;
843
- }
844
- value &= (1 << bits) - 1;
845
- }
846
- if (bits > 0)
847
- out += B32.charAt((value << (5 - bits)) & 31);
848
- return out;
849
- }
850
- /** Standard or URL-safe base64 (padded or not) → unpadded base64url. */
851
- function base64url(s) {
852
- return s.replace(/\s+/g, '').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
853
- }
854
- function pem(b64) {
855
- const body = b64.replace(/-----[^-]+-----/g, '').replace(/\s+/g, '');
856
- return `-----BEGIN CERTIFICATE-----\n${body.match(/.{1,64}/g).join('\n')}\n-----END CERTIFICATE-----`;
857
- }
858
- /** Export a realm from an export file (hashes and OTP secrets included) or the Admin API (no secrets). */
859
- async function exportKeycloak(o) {
860
- let snap;
861
- if (o.exportDocs) {
862
- snap = readKeycloakExport(o.exportDocs, o.realm);
863
- if (o.api?.baseUrl)
864
- snap.baseUrl = keycloakBase(o.api.baseUrl);
865
- }
866
- else {
867
- if (!o.api || !o.realm)
868
- throw new Error('Keycloak: name the realm and give an admin credential, or a realm export.');
869
- const warnings = [];
870
- snap = await fetchKeycloakRealm(keycloakAdminHttp({ ...o.api, realm: o.realm }), { realm: o.realm, baseUrl: o.api.baseUrl, onProgress: o.onProgress, warn: (m) => warnings.push(m) });
871
- const set = mapKeycloak(snap, o);
872
- for (const w of warnings)
873
- set.warn(w);
874
- return set;
875
- }
876
- return mapKeycloak(snap, o);
877
- }
878
- //# sourceMappingURL=keycloak.js.map