@atlasauth/cli 0.11.0 → 0.12.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 (127) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/args.d.ts +106 -0
  3. package/dist/args.js +38 -0
  4. package/dist/args.js.map +1 -1
  5. package/dist/commands/init.js +13 -8
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/migrate.d.ts +6 -2
  8. package/dist/commands/migrate.js +13 -3
  9. package/dist/commands/migrate.js.map +1 -1
  10. package/dist/help.d.ts +1 -1
  11. package/dist/help.js +38 -0
  12. package/dist/help.js.map +1 -1
  13. package/dist/migrate/auth0/plugin.d.ts +2 -0
  14. package/dist/migrate/auth0/plugin.js +126 -0
  15. package/dist/migrate/auth0/plugin.js.map +1 -0
  16. package/dist/migrate/clerk/plugin.d.ts +2 -0
  17. package/dist/migrate/clerk/plugin.js +76 -0
  18. package/dist/migrate/clerk/plugin.js.map +1 -0
  19. package/dist/migrate/descope/plugin.d.ts +2 -0
  20. package/dist/migrate/descope/plugin.js +83 -0
  21. package/dist/migrate/descope/plugin.js.map +1 -0
  22. package/dist/migrate/export/auth0-config.d.ts +29 -0
  23. package/dist/migrate/export/auth0-config.js +249 -0
  24. package/dist/migrate/export/auth0-config.js.map +1 -0
  25. package/dist/migrate/export/auth0.d.ts +62 -0
  26. package/dist/migrate/export/auth0.js +575 -0
  27. package/dist/migrate/export/auth0.js.map +1 -0
  28. package/dist/migrate/export/clerk-config.d.ts +26 -0
  29. package/dist/migrate/export/clerk-config.js +227 -0
  30. package/dist/migrate/export/clerk-config.js.map +1 -0
  31. package/dist/migrate/export/clerk.d.ts +46 -0
  32. package/dist/migrate/export/clerk.js +486 -0
  33. package/dist/migrate/export/clerk.js.map +1 -0
  34. package/dist/migrate/export/descope.d.ts +35 -0
  35. package/dist/migrate/export/descope.js +208 -0
  36. package/dist/migrate/export/descope.js.map +1 -0
  37. package/dist/migrate/export/fake-vendor.test-helper.d.ts +27 -0
  38. package/dist/migrate/export/fake-vendor.test-helper.js +41 -0
  39. package/dist/migrate/export/fake-vendor.test-helper.js.map +1 -0
  40. package/dist/migrate/export/frameworks/app-users.d.ts +42 -0
  41. package/dist/migrate/export/frameworks/app-users.js +161 -0
  42. package/dist/migrate/export/frameworks/app-users.js.map +1 -0
  43. package/dist/migrate/export/frameworks/authjs.d.ts +41 -0
  44. package/dist/migrate/export/frameworks/authjs.js +146 -0
  45. package/dist/migrate/export/frameworks/authjs.js.map +1 -0
  46. package/dist/migrate/export/frameworks/devise.d.ts +39 -0
  47. package/dist/migrate/export/frameworks/devise.js +218 -0
  48. package/dist/migrate/export/frameworks/devise.js.map +1 -0
  49. package/dist/migrate/export/frameworks/django.d.ts +45 -0
  50. package/dist/migrate/export/frameworks/django.js +315 -0
  51. package/dist/migrate/export/frameworks/django.js.map +1 -0
  52. package/dist/migrate/export/frameworks/lucia.d.ts +42 -0
  53. package/dist/migrate/export/frameworks/lucia.js +263 -0
  54. package/dist/migrate/export/frameworks/lucia.js.map +1 -0
  55. package/dist/migrate/export/frameworks/tables.d.ts +90 -0
  56. package/dist/migrate/export/frameworks/tables.js +325 -0
  57. package/dist/migrate/export/frameworks/tables.js.map +1 -0
  58. package/dist/migrate/export/frameworks/webauthn.d.ts +25 -0
  59. package/dist/migrate/export/frameworks/webauthn.js +130 -0
  60. package/dist/migrate/export/frameworks/webauthn.js.map +1 -0
  61. package/dist/migrate/export/kinde-descope-config.d.ts +38 -0
  62. package/dist/migrate/export/kinde-descope-config.js +172 -0
  63. package/dist/migrate/export/kinde-descope-config.js.map +1 -0
  64. package/dist/migrate/export/kinde.d.ts +57 -0
  65. package/dist/migrate/export/kinde.js +333 -0
  66. package/dist/migrate/export/kinde.js.map +1 -0
  67. package/dist/migrate/export/okta-config.d.ts +30 -0
  68. package/dist/migrate/export/okta-config.js +205 -0
  69. package/dist/migrate/export/okta-config.js.map +1 -0
  70. package/dist/migrate/export/okta.d.ts +43 -0
  71. package/dist/migrate/export/okta.js +337 -0
  72. package/dist/migrate/export/okta.js.map +1 -0
  73. package/dist/migrate/export/plugin-kit.d.ts +25 -0
  74. package/dist/migrate/export/plugin-kit.js +82 -0
  75. package/dist/migrate/export/plugin-kit.js.map +1 -0
  76. package/dist/migrate/export/record-set.d.ts +44 -0
  77. package/dist/migrate/export/record-set.js +98 -0
  78. package/dist/migrate/export/record-set.js.map +1 -0
  79. package/dist/migrate/export/translate-kit.d.ts +46 -0
  80. package/dist/migrate/export/translate-kit.js +148 -0
  81. package/dist/migrate/export/translate-kit.js.map +1 -0
  82. package/dist/migrate/export/vendor-http.d.ts +46 -0
  83. package/dist/migrate/export/vendor-http.js +138 -0
  84. package/dist/migrate/export/vendor-http.js.map +1 -0
  85. package/dist/migrate/export/zip.d.ts +8 -0
  86. package/dist/migrate/export/zip.js +66 -0
  87. package/dist/migrate/export/zip.js.map +1 -0
  88. package/dist/migrate/framework/builtins.d.ts +2 -0
  89. package/dist/migrate/framework/builtins.js +23 -0
  90. package/dist/migrate/framework/builtins.js.map +1 -0
  91. package/dist/migrate/framework/commands.d.ts +20 -0
  92. package/dist/migrate/framework/commands.js +58 -0
  93. package/dist/migrate/framework/commands.js.map +1 -0
  94. package/dist/migrate/framework/custom.d.ts +12 -0
  95. package/dist/migrate/framework/custom.js +96 -0
  96. package/dist/migrate/framework/custom.js.map +1 -0
  97. package/dist/migrate/framework/orchestrator.d.ts +113 -0
  98. package/dist/migrate/framework/orchestrator.js +531 -0
  99. package/dist/migrate/framework/orchestrator.js.map +1 -0
  100. package/dist/migrate/framework/plugin.d.ts +165 -0
  101. package/dist/migrate/framework/plugin.js +3 -0
  102. package/dist/migrate/framework/plugin.js.map +1 -0
  103. package/dist/migrate/framework/registry.d.ts +11 -0
  104. package/dist/migrate/framework/registry.js +44 -0
  105. package/dist/migrate/framework/registry.js.map +1 -0
  106. package/dist/migrate/framework/report.d.ts +17 -0
  107. package/dist/migrate/framework/report.js +103 -0
  108. package/dist/migrate/framework/report.js.map +1 -0
  109. package/dist/migrate/frameworks/plugins.d.ts +29 -0
  110. package/dist/migrate/frameworks/plugins.js +402 -0
  111. package/dist/migrate/frameworks/plugins.js.map +1 -0
  112. package/dist/migrate/frameworks/report.d.ts +92 -0
  113. package/dist/migrate/frameworks/report.js +207 -0
  114. package/dist/migrate/frameworks/report.js.map +1 -0
  115. package/dist/migrate/frameworks/translate-js.d.ts +5 -0
  116. package/dist/migrate/frameworks/translate-js.js +503 -0
  117. package/dist/migrate/frameworks/translate-js.js.map +1 -0
  118. package/dist/migrate/frameworks/translate-rails-django.d.ts +3 -0
  119. package/dist/migrate/frameworks/translate-rails-django.js +1391 -0
  120. package/dist/migrate/frameworks/translate-rails-django.js.map +1 -0
  121. package/dist/migrate/kinde/plugin.d.ts +2 -0
  122. package/dist/migrate/kinde/plugin.js +105 -0
  123. package/dist/migrate/kinde/plugin.js.map +1 -0
  124. package/dist/migrate/okta/plugin.d.ts +2 -0
  125. package/dist/migrate/okta/plugin.js +105 -0
  126. package/dist/migrate/okta/plugin.js.map +1 -0
  127. package/package.json +5 -4
@@ -0,0 +1,315 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DJANGO_EXPORT_SCRIPT = void 0;
4
+ exports.exportDjango = exportDjango;
5
+ exports.decodeSessionData = decodeSessionData;
6
+ const node_zlib_1 = require("node:zlib");
7
+ const tables_1 = require("./tables");
8
+ const webauthn_1 = require("./webauthn");
9
+ function fixtures(tables) {
10
+ const byModel = new Map();
11
+ for (const name of tables.names()) {
12
+ for (const row of tables.rows(name)) {
13
+ const model = (0, tables_1.text)(row.model)?.toLowerCase();
14
+ const fields = (0, tables_1.json)(row.fields);
15
+ if (!model || !fields)
16
+ continue;
17
+ const list = byModel.get(model) ?? [];
18
+ list.push({ model, pk: row.pk, fields });
19
+ byModel.set(model, list);
20
+ }
21
+ }
22
+ return byModel;
23
+ }
24
+ function exportDjango(tables, options = {}) {
25
+ const out = new tables_1.FrameworkExport();
26
+ const now = (options.now ?? new Date()).getTime();
27
+ const fx = fixtures(tables);
28
+ const userModel = options.userModel?.toLowerCase() ??
29
+ (fx.has('auth.user')
30
+ ? 'auth.user'
31
+ : [...fx.keys()].find((m) => {
32
+ const f = fx.get(m)[0].fields;
33
+ return 'password' in f && ('username' in f || 'email' in f) && 'last_login' in f;
34
+ }));
35
+ if (!userModel || !fx.has(userModel)) {
36
+ out.warn('No user model rows found: dump auth.user (or your AUTH_USER_MODEL) with manage.py dumpdata.');
37
+ return out;
38
+ }
39
+ // Groups → app roles (permission codenames when auth.permission was dumped).
40
+ const permissions = new Map();
41
+ for (const p of fx.get('auth.permission') ?? []) {
42
+ const codename = (0, tables_1.text)(p.fields.codename);
43
+ if (codename)
44
+ permissions.set(String(p.pk), codename);
45
+ }
46
+ const groups = new Map();
47
+ for (const g of fx.get('auth.group') ?? []) {
48
+ const name = (0, tables_1.text)(g.fields.name);
49
+ if (!name)
50
+ continue;
51
+ groups.set(String(g.pk), name);
52
+ const perms = (Array.isArray(g.fields.permissions) ? g.fields.permissions : [])
53
+ .map((pk) => (Array.isArray(pk) ? (0, tables_1.text)(pk[0]) : permissions.get(String(pk))))
54
+ .filter((p) => Boolean(p));
55
+ out.add('role', { key: name, name, scope: 'app', permissions: perms.length ? perms : undefined });
56
+ }
57
+ const emails = new Map();
58
+ for (const e of fx.get('account.emailaddress') ?? []) {
59
+ const uid = (0, tables_1.text)(e.fields.user);
60
+ const email = (0, tables_1.text)(e.fields.email)?.toLowerCase();
61
+ if (!uid || !email)
62
+ continue;
63
+ const list = emails.get(uid) ?? [];
64
+ list.push({ email, verified: (0, tables_1.bool)(e.fields.verified), primary: (0, tables_1.bool)(e.fields.primary) });
65
+ emails.set(uid, list);
66
+ }
67
+ const allauth = fx.has('account.emailaddress');
68
+ const ids = new Set();
69
+ let unusable = 0;
70
+ for (const u of fx.get(userModel)) {
71
+ const id = (0, tables_1.text)(u.pk);
72
+ if (!id)
73
+ continue;
74
+ const f = u.fields;
75
+ const email = (0, tables_1.text)(f.email)?.toLowerCase();
76
+ const list = emails.get(id) ?? (email ? [{ email, verified: options.trustEmails === true, primary: true }] : []);
77
+ const username = (0, tables_1.text)(f.username);
78
+ if (!list.length && !username) {
79
+ out.omit('user', 'no email or username');
80
+ continue;
81
+ }
82
+ const digest = (0, tables_1.text)(f.password);
83
+ const usable = Boolean(digest) && !digest.startsWith('!');
84
+ if (!usable && digest)
85
+ unusable++;
86
+ const roles = (Array.isArray(f.groups) ? f.groups : [])
87
+ .map((g) => (Array.isArray(g) ? (0, tables_1.text)(g[0]) : groups.get(String(g))))
88
+ .filter((g) => Boolean(g));
89
+ if ((0, tables_1.bool)(f.is_superuser))
90
+ roles.push('superuser');
91
+ if ((0, tables_1.bool)(f.is_staff))
92
+ roles.push('staff');
93
+ const active = f.is_active === undefined ? true : (0, tables_1.bool)(f.is_active);
94
+ ids.add(id);
95
+ out.add('user', {
96
+ id,
97
+ emails: list,
98
+ username,
99
+ first_name: (0, tables_1.text)(f.first_name),
100
+ last_name: (0, tables_1.text)(f.last_name),
101
+ password: usable ? { algorithm: 'auto', hash: digest } : undefined,
102
+ roles: roles.length ? [...new Set(roles)] : undefined,
103
+ banned: active ? undefined : true,
104
+ ban_reason: active ? undefined : 'is_active was false in Django',
105
+ created_at: (0, tables_1.time)(f.date_joined),
106
+ last_sign_in_at: (0, tables_1.time)(f.last_login),
107
+ });
108
+ }
109
+ if (unusable)
110
+ out.warn(`${unusable} user(s) had an unusable password (social-only or set_unusable_password): they sign in through their identities.`);
111
+ if (!allauth)
112
+ out.warn('django-allauth email addresses were not in the dump: email verification state comes from --trust-emails.');
113
+ for (const key of ['superuser', 'staff']) {
114
+ const used = out.list('user').some((u) => u.roles?.includes(key));
115
+ if (used && !out.list('role').some((r) => r.key === key))
116
+ out.add('role', { key, name: key, scope: 'app' });
117
+ }
118
+ // Social accounts (+ tokens).
119
+ const tokens = new Map();
120
+ for (const t of fx.get('socialaccount.socialtoken') ?? []) {
121
+ const account = (0, tables_1.text)(t.fields.account);
122
+ if (account)
123
+ tokens.set(account, t.fields);
124
+ }
125
+ const providers = new Set();
126
+ for (const s of fx.get('socialaccount.socialaccount') ?? []) {
127
+ const uid = (0, tables_1.text)(s.fields.user);
128
+ const provider = (0, tables_1.text)(s.fields.provider);
129
+ const subject = (0, tables_1.text)(s.fields.uid);
130
+ if (!uid || !provider || !subject || !ids.has(uid)) {
131
+ out.omit('identity', 'social account without a known user, provider or uid');
132
+ continue;
133
+ }
134
+ providers.add(provider);
135
+ const token = tokens.get(String(s.pk));
136
+ const extra = (0, tables_1.json)(s.fields.extra_data);
137
+ out.add('identity', {
138
+ user_id: uid,
139
+ provider,
140
+ provider_user_id: subject,
141
+ kind: provider === 'openid_connect' || provider === 'saml' ? (provider === 'saml' ? 'saml' : 'oidc') : 'oauth',
142
+ email: (0, tables_1.text)(extra?.email),
143
+ profile: extra,
144
+ ...(options.oauthTokens && token
145
+ ? { access_token: (0, tables_1.text)(token.token), refresh_token: (0, tables_1.text)(token.token_secret), expires_at: (0, tables_1.time)(token.expires_at) }
146
+ : {}),
147
+ });
148
+ }
149
+ out.manifest.providers = [...providers].sort();
150
+ // allauth MFA. The script's decrypted extras win over the dump's raw data.
151
+ const extras = tables.rows('mfa_secrets');
152
+ const extraBy = new Map(extras.map((r) => [`${(0, tables_1.text)(r.authenticator_id)}`, r]));
153
+ const rawPasskeys = [];
154
+ for (const a of fx.get('mfa.authenticator') ?? []) {
155
+ const uid = (0, tables_1.text)(a.fields.user);
156
+ const type = (0, tables_1.text)(a.fields.type);
157
+ const data = (0, tables_1.json)(a.fields.data) ?? {};
158
+ if (!uid || !ids.has(uid))
159
+ continue;
160
+ const extra = extraBy.get(String(a.pk));
161
+ if (type === 'totp') {
162
+ const secret = (0, tables_1.text)(extra?.secret) ?? (0, tables_1.text)(data.secret);
163
+ if (!secret || !/^[A-Z2-7]+=*$/i.test(secret)) {
164
+ out.omit('mfa_factor', 'TOTP secret encrypted by a custom MFA adapter: run the export script so the adapter decrypts it');
165
+ continue;
166
+ }
167
+ out.add('mfa_factor', { user_id: uid, type: 'totp', secret_base32: secret.toUpperCase(), digits: 6, period: 30, algorithm: 'SHA1', verified: true, created_at: (0, tables_1.time)(a.fields.created_at) });
168
+ }
169
+ else if (type === 'recovery_codes') {
170
+ const codes = Array.isArray(extra?.codes) ? extra.codes.map(String) : [];
171
+ if (!codes.length) {
172
+ out.omit('mfa_factor', 'recovery codes are derived from an encrypted seed: run the export script to carry the unused ones');
173
+ continue;
174
+ }
175
+ out.add('mfa_factor', { user_id: uid, type: 'backup_codes', backup_codes: codes });
176
+ }
177
+ else if (type === 'webauthn') {
178
+ rawPasskeys.push(a);
179
+ }
180
+ }
181
+ if (rawPasskeys.length && !options.rpId) {
182
+ out.omit('passkey', 'no RP id given (--rp-id): a passkey only works on the domain it was registered for', rawPasskeys.length);
183
+ }
184
+ for (const a of options.rpId ? rawPasskeys : []) {
185
+ const data = (0, tables_1.json)(a.fields.data) ?? {};
186
+ const credential = (0, tables_1.json)(data.credential);
187
+ const response = (0, tables_1.json)(credential?.response);
188
+ const parsed = typeof response?.attestationObject === 'string' ? (0, webauthn_1.parseAttestationObject)(response.attestationObject) : null;
189
+ if (!parsed) {
190
+ out.omit('passkey', 'WebAuthn authenticator whose registration response could not be read');
191
+ continue;
192
+ }
193
+ out.add('passkey', {
194
+ user_id: (0, tables_1.text)(a.fields.user),
195
+ credential_id: parsed.credentialId.toString('base64url'),
196
+ public_key: parsed.publicKey.toString('base64url'),
197
+ sign_count: parsed.signCount,
198
+ aaguid: parsed.aaguid,
199
+ backed_up: parsed.backedUp,
200
+ transports: Array.isArray(response?.transports) ? response.transports.map(String) : undefined,
201
+ rp_id: options.rpId,
202
+ name: (0, tables_1.text)(data.name),
203
+ created_at: (0, tables_1.time)(a.fields.created_at),
204
+ });
205
+ }
206
+ if (options.rpId)
207
+ out.manifest.rpId = options.rpId;
208
+ // Database-backed sessions.
209
+ if (options.sessions !== false) {
210
+ for (const s of fx.get('sessions.session') ?? []) {
211
+ const key = (0, tables_1.text)(s.pk);
212
+ const expires = (0, tables_1.timeMs)(s.fields.expire_date);
213
+ const data = decodeSessionData(String(s.fields.session_data ?? ''));
214
+ const uid = (0, tables_1.text)(data?._auth_user_id);
215
+ if (!key || expires === undefined || !data) {
216
+ out.omit('session', 'session row that could not be decoded');
217
+ continue;
218
+ }
219
+ if (!uid) {
220
+ out.omit('session', 'anonymous session');
221
+ continue;
222
+ }
223
+ if (!ids.has(uid)) {
224
+ out.omit('session', 'session of a user not in the export');
225
+ continue;
226
+ }
227
+ if (expires <= now) {
228
+ out.omit('session', 'expired');
229
+ continue;
230
+ }
231
+ out.add('session', { id: (0, tables_1.sha256Hex)(key).slice(0, 32), user_id: uid, token_hash: (0, tables_1.sha256Hex)(key), expires_at: new Date(expires).toISOString() });
232
+ }
233
+ }
234
+ out.manifest.settings = { session_cookie: 'sessionid' };
235
+ return out;
236
+ }
237
+ /**
238
+ * Decode `django_session.session_data` without the SECRET_KEY (the rows come
239
+ * from the app's own database): Django ≥ 3.1 `signing.dumps` (`payload:ts:sig`,
240
+ * payload zlib-compressed when it starts with `.`), and the pre-3.1 form,
241
+ * base64(`<hash>:<json>`).
242
+ */
243
+ function decodeSessionData(raw) {
244
+ const value = raw.trim();
245
+ if (!value)
246
+ return null;
247
+ try {
248
+ if (value.split(':').length === 3) {
249
+ const payload = value.split(':')[0];
250
+ const compressed = payload.startsWith('.');
251
+ const bytes = Buffer.from(compressed ? payload.slice(1) : payload, 'base64url');
252
+ const parsed = JSON.parse((compressed ? (0, node_zlib_1.inflateSync)(bytes) : bytes).toString('utf8'));
253
+ return (0, tables_1.json)(parsed) ?? null;
254
+ }
255
+ const legacy = Buffer.from(value, 'base64').toString('utf8');
256
+ const colon = legacy.indexOf(':');
257
+ if (colon < 0)
258
+ return null;
259
+ return (0, tables_1.json)(legacy.slice(colon + 1)) ?? null;
260
+ }
261
+ catch {
262
+ return null;
263
+ }
264
+ }
265
+ /**
266
+ * The export script, run inside the Django app so allauth's own code decrypts
267
+ * TOTP secrets and lists the unused recovery codes; it streams NDJSON straight
268
+ * into the CLI:
269
+ *
270
+ * python manage.py shell < atlas_export.py | npx atlas migrate django export --file -
271
+ */
272
+ exports.DJANGO_EXPORT_SCRIPT = `# Atlas export for a Django app (django.contrib.auth + django-allauth).
273
+ import io, json, sys
274
+ from django.apps import apps
275
+ from django.conf import settings
276
+ from django.core.management import call_command
277
+
278
+ def emit(table, row):
279
+ sys.stdout.write(json.dumps({"table": table, "row": row}, default=str) + "\\n")
280
+
281
+ labels = [settings.AUTH_USER_MODEL, "auth.group", "auth.permission"]
282
+ for label in ["account.emailaddress", "socialaccount.socialaccount", "socialaccount.socialtoken", "mfa.authenticator", "sessions.session"]:
283
+ try:
284
+ apps.get_model(label)
285
+ labels.append(label)
286
+ except (LookupError, ValueError):
287
+ pass
288
+
289
+ buf = io.StringIO()
290
+ call_command("dumpdata", *labels, format="json", stdout=buf)
291
+ for obj in json.loads(buf.getvalue()):
292
+ emit("dumpdata", obj)
293
+
294
+ try:
295
+ from allauth.mfa.models import Authenticator
296
+ from allauth.mfa.adapter import get_adapter
297
+ except ImportError:
298
+ Authenticator = None
299
+
300
+ if Authenticator is not None:
301
+ try:
302
+ from allauth.mfa.recovery_codes.internal.auth import RecoveryCodes
303
+ except ImportError:
304
+ try:
305
+ from allauth.mfa.recovery_codes import RecoveryCodes
306
+ except ImportError:
307
+ RecoveryCodes = None
308
+ adapter = get_adapter()
309
+ for a in Authenticator.objects.all():
310
+ if a.type == "totp":
311
+ emit("mfa_secrets", {"authenticator_id": a.pk, "secret": adapter.decrypt(a.data["secret"])})
312
+ elif a.type == "recovery_codes" and RecoveryCodes is not None:
313
+ emit("mfa_secrets", {"authenticator_id": a.pk, "codes": RecoveryCodes(a).get_unused_codes()})
314
+ `;
315
+ //# sourceMappingURL=django.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"django.js","sourceRoot":"","sources":["../../../../src/migrate/export/frameworks/django.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { FrameworkExport, type Tables } from './tables';
2
+ /**
3
+ * Lucia → canonical records. Lucia never owned a schema the way an adapter
4
+ * library does, so three generations are recognised:
5
+ *
6
+ * - v1 / v2: `auth_user`, `user_key` / `auth_key` (key id `<provider>:<provider
7
+ * user id>`, `hashed_password` on email/username keys, Lucia's own
8
+ * `s2:` scrypt) and `user_session` / `auth_session` (`active_expires`,
9
+ * `idle_expires` in epoch ms);
10
+ * - v3: your `user` table, `session(id, user_id, expires_at)`, OAuth links in
11
+ * a table you named (`oauth_account(provider_id, provider_user_id, user_id)`
12
+ * by the docs) or `<provider>_id` columns on the user (`github_id`), and a
13
+ * password column you filled with oslo's Argon2id / Scrypt / Bcrypt;
14
+ * - the current Lucia guide (sessions you implement): `session.id` is
15
+ * hex(sha256(token)); TOTP keys in `totp_credential.key` and the recovery
16
+ * code in `user.recovery_code`, both AES-128-GCM encrypted under your
17
+ * ENCRYPTION_KEY; passkeys in `passkey_credential` with a SEC1 public key.
18
+ */
19
+ export interface LuciaExportOptions {
20
+ /** How session rows store the cookie token: `none` (v2/v3, the id IS the token) or `sha256-hex` (the guide). Auto-detected. */
21
+ sessionIdHashing?: 'none' | 'sha256-hex';
22
+ /** The guide's ENCRYPTION_KEY (base64), to read encrypted TOTP keys and recovery codes. */
23
+ encryptionKey?: string;
24
+ /** WebAuthn RP id, for passkey_credential rows. */
25
+ rpId?: string;
26
+ /** Include live sessions. Default true. */
27
+ sessions?: boolean;
28
+ /** Table name overrides. */
29
+ userTable?: string;
30
+ sessionTable?: string;
31
+ oauthTable?: string;
32
+ now?: Date;
33
+ }
34
+ export declare function exportLucia(tables: Tables, options?: LuciaExportOptions): FrameworkExport;
35
+ /** The guide's `encrypt()`: iv(16) ‖ ciphertext ‖ tag(16), AES-128-GCM (AES-256 for a 32-byte key). */
36
+ export declare function decryptGuideValue(v: unknown, key: Buffer): Buffer | null;
37
+ export declare function base32(data: Buffer): string;
38
+ /**
39
+ * An uncompressed SEC1 P-256 key (0x04 ‖ x ‖ y) as a COSE_Key:
40
+ * {1: 2 (EC2), 3: -7 (ES256), -1: 1 (P-256), -2: x, -3: y}, CBOR-encoded.
41
+ */
42
+ export declare function coseFromSec1(key: Buffer | null): Buffer | null;
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exportLucia = exportLucia;
4
+ exports.decryptGuideValue = decryptGuideValue;
5
+ exports.base32 = base32;
6
+ exports.coseFromSec1 = coseFromSec1;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const tables_1 = require("./tables");
9
+ const PASSWORD_COLUMNS = ['password_hash', 'hashed_password', 'passwordHash', 'hashedPassword', 'password'];
10
+ const PROVIDER_COLUMNS = {
11
+ github_id: 'github',
12
+ google_id: 'google',
13
+ discord_id: 'discord',
14
+ apple_id: 'apple',
15
+ gitlab_id: 'gitlab',
16
+ twitter_id: 'twitter',
17
+ facebook_id: 'facebook',
18
+ microsoft_id: 'microsoft',
19
+ twitch_id: 'twitch',
20
+ spotify_id: 'spotify',
21
+ };
22
+ function exportLucia(tables, options = {}) {
23
+ const out = new tables_1.FrameworkExport();
24
+ const now = (options.now ?? new Date()).getTime();
25
+ const userTable = tables.find(...(options.userTable ? [options.userTable] : ['auth_user', 'user', 'users', 'User']));
26
+ if (!userTable) {
27
+ out.warn('No user table found (looked for auth_user, user, users; pass --user-table).');
28
+ return out;
29
+ }
30
+ const keyTable = tables.find('user_key', 'auth_key', 'key');
31
+ const generation = keyTable ? 'v2' : 'v3';
32
+ out.manifest.sourceVersion = generation === 'v2' ? 'lucia v1/v2' : 'lucia v3 / guide';
33
+ // v2 keys: email/username keys carry the password; others are OAuth links.
34
+ const keysByUser = new Map();
35
+ for (const k of keyTable?.rows ?? []) {
36
+ const uid = (0, tables_1.text)((0, tables_1.col)(k, 'user_id', 'userId'));
37
+ if (!uid)
38
+ continue;
39
+ const list = keysByUser.get(uid) ?? [];
40
+ list.push(k);
41
+ keysByUser.set(uid, list);
42
+ }
43
+ const key = options.encryptionKey ? Buffer.from(options.encryptionKey, 'base64') : undefined;
44
+ const userIds = new Set();
45
+ const providers = new Set();
46
+ let unknownHashes = 0;
47
+ for (const row of userTable.rows) {
48
+ const id = (0, tables_1.text)((0, tables_1.col)(row, 'id', '_id'));
49
+ if (!id) {
50
+ out.omit('user', 'row without an id');
51
+ continue;
52
+ }
53
+ let email = (0, tables_1.text)((0, tables_1.col)(row, 'email', 'email_address'))?.toLowerCase();
54
+ let username = (0, tables_1.text)((0, tables_1.col)(row, 'username'));
55
+ let digest = (0, tables_1.text)((0, tables_1.col)(row, ...PASSWORD_COLUMNS));
56
+ const identities = [];
57
+ for (const k of keysByUser.get(id) ?? []) {
58
+ const keyId = (0, tables_1.text)((0, tables_1.col)(k, 'id'));
59
+ if (!keyId || !keyId.includes(':'))
60
+ continue;
61
+ const provider = keyId.slice(0, keyId.indexOf(':'));
62
+ const subject = keyId.slice(keyId.indexOf(':') + 1);
63
+ if (provider === 'email') {
64
+ email ??= subject.toLowerCase();
65
+ digest ??= (0, tables_1.text)((0, tables_1.col)(k, 'hashed_password'));
66
+ }
67
+ else if (provider === 'username') {
68
+ username ??= subject;
69
+ digest ??= (0, tables_1.text)((0, tables_1.col)(k, 'hashed_password'));
70
+ }
71
+ else
72
+ identities.push({ provider, subject });
73
+ }
74
+ for (const [column, provider] of Object.entries(PROVIDER_COLUMNS)) {
75
+ const subject = (0, tables_1.text)(row[column]);
76
+ if (subject)
77
+ identities.push({ provider, subject });
78
+ }
79
+ if (!email && !username) {
80
+ out.omit('user', 'no email or username');
81
+ continue;
82
+ }
83
+ let password;
84
+ if (digest) {
85
+ password = (0, tables_1.selfDescribingHash)(digest) ?? undefined;
86
+ if (!password)
87
+ unknownHashes++;
88
+ }
89
+ const name = (0, tables_1.text)((0, tables_1.col)(row, 'name', 'display_name'));
90
+ userIds.add(id);
91
+ out.add('user', {
92
+ id,
93
+ emails: email ? [{ email, verified: (0, tables_1.bool)((0, tables_1.col)(row, 'email_verified', 'emailVerified')), primary: true }] : undefined,
94
+ username,
95
+ name,
96
+ ...(0, tables_1.splitName)(name),
97
+ password,
98
+ created_at: (0, tables_1.time)((0, tables_1.col)(row, 'created_at', 'createdAt')),
99
+ });
100
+ for (const i of identities) {
101
+ providers.add(i.provider);
102
+ out.add('identity', { user_id: id, provider: i.provider, provider_user_id: i.subject, kind: 'oauth' });
103
+ }
104
+ // The guide's recovery code: one encrypted code on the user row.
105
+ const recovery = (0, tables_1.col)(row, 'recovery_code');
106
+ if (recovery !== undefined && key) {
107
+ const code = decryptGuideValue(recovery, key);
108
+ if (code)
109
+ out.add('mfa_factor', { user_id: id, type: 'backup_codes', backup_codes: [code.toString('utf8')] });
110
+ else
111
+ out.omit('mfa_factor', 'recovery code that does not decrypt under the ENCRYPTION_KEY given');
112
+ }
113
+ }
114
+ if (unknownHashes)
115
+ out.warn(`${unknownHashes} password value(s) are not a format Atlas verifies: those users reset their password or migrate lazily.`);
116
+ const oauth = tables.find(...(options.oauthTable ? [options.oauthTable] : ['oauth_account', 'oauth_accounts', 'account']));
117
+ for (const row of oauth?.rows ?? []) {
118
+ const userId = (0, tables_1.text)((0, tables_1.col)(row, 'user_id', 'userId'));
119
+ const provider = (0, tables_1.text)((0, tables_1.col)(row, 'provider_id', 'provider'));
120
+ const subject = (0, tables_1.text)((0, tables_1.col)(row, 'provider_user_id', 'providerUserId'));
121
+ if (!userId || !provider || !subject || !userIds.has(userId)) {
122
+ out.omit('identity', 'oauth account row without a known user, provider or provider user id');
123
+ continue;
124
+ }
125
+ providers.add(provider);
126
+ out.add('identity', { user_id: userId, provider, provider_user_id: subject, kind: 'oauth' });
127
+ }
128
+ out.manifest.providers = [...providers].sort();
129
+ // The guide's TOTP credentials.
130
+ const totp = tables.rows('totp_credential', 'totp_credentials');
131
+ if (totp.length && !key) {
132
+ out.omit('mfa_factor', 'TOTP keys are encrypted: pass --encryption-key (your ENCRYPTION_KEY) to carry them', totp.length);
133
+ }
134
+ for (const row of key ? totp : []) {
135
+ const userId = (0, tables_1.text)((0, tables_1.col)(row, 'user_id', 'userId'));
136
+ const secret = decryptGuideValue((0, tables_1.col)(row, 'key'), key);
137
+ if (!userId || !userIds.has(userId) || !secret) {
138
+ out.omit('mfa_factor', 'TOTP row without a known user, or a key that does not decrypt');
139
+ continue;
140
+ }
141
+ out.add('mfa_factor', { user_id: userId, type: 'totp', secret_base32: base32(secret), digits: 6, period: 30, algorithm: 'SHA1', verified: true });
142
+ }
143
+ // The guide's passkeys: SEC1 P-256 public keys (COSE alg -7) are re-encoded as COSE.
144
+ const passkeys = tables.rows('passkey_credential', 'passkey_credentials');
145
+ if (passkeys.length && !options.rpId) {
146
+ out.omit('passkey', 'no RP id given (--rp-id): a passkey only works on the domain it was registered for', passkeys.length);
147
+ }
148
+ for (const row of options.rpId ? passkeys : []) {
149
+ const userId = (0, tables_1.text)((0, tables_1.col)(row, 'user_id', 'userId'));
150
+ const credentialId = bytesOf((0, tables_1.col)(row, 'id'));
151
+ const alg = Number((0, tables_1.col)(row, 'algorithm', 'algorithm_id'));
152
+ const cose = alg === -7 ? coseFromSec1(bytesOf((0, tables_1.col)(row, 'public_key'))) : null;
153
+ if (!userId || !userIds.has(userId) || !credentialId || !cose) {
154
+ out.omit('passkey', alg === -7 ? 'passkey row without a known user or a readable key' : 'passkey with an algorithm other than ES256 (re-register it)');
155
+ continue;
156
+ }
157
+ out.add('passkey', {
158
+ user_id: userId,
159
+ credential_id: credentialId.toString('base64url'),
160
+ public_key: cose.toString('base64url'),
161
+ rp_id: options.rpId,
162
+ name: (0, tables_1.text)((0, tables_1.col)(row, 'name')),
163
+ });
164
+ }
165
+ if (options.rpId)
166
+ out.manifest.rpId = options.rpId;
167
+ if (options.sessions !== false) {
168
+ const sessions = tables.find(...(options.sessionTable ? [options.sessionTable] : ['user_session', 'auth_session', 'session', 'sessions']));
169
+ const hashing = options.sessionIdHashing ?? detectHashing(sessions?.rows ?? []);
170
+ for (const row of sessions?.rows ?? []) {
171
+ const sid = (0, tables_1.text)((0, tables_1.col)(row, 'id'));
172
+ const userId = (0, tables_1.text)((0, tables_1.col)(row, 'user_id', 'userId'));
173
+ // v2 sessions stay usable until idle_expires (Lucia renews them on use).
174
+ const expires = (0, tables_1.timeMs)((0, tables_1.col)(row, 'idle_expires', 'expires_at', 'expiresAt', 'active_expires'));
175
+ if (!sid || !userId || !userIds.has(userId) || expires === undefined) {
176
+ out.omit('session', 'session row without an id, a known user or an expiry');
177
+ continue;
178
+ }
179
+ if (expires <= now) {
180
+ out.omit('session', 'expired');
181
+ continue;
182
+ }
183
+ out.add('session', {
184
+ id: sid.slice(0, 64),
185
+ user_id: userId,
186
+ // The bridge hashes the cookie token: for guide sessions the stored id already is that hash.
187
+ token_hash: hashing === 'sha256-hex' ? sid.toLowerCase() : (0, tables_1.sha256Hex)(sid),
188
+ expires_at: new Date(expires).toISOString(),
189
+ });
190
+ }
191
+ out.manifest.settings = { session_cookie: 'auth_session', session_id_hashing: hashing };
192
+ }
193
+ return out;
194
+ }
195
+ /** Guide sessions store 64-char lowercase hex ids; Lucia v2/v3 ids are 15–40 char alphanumerics. */
196
+ function detectHashing(rows) {
197
+ if (!rows.length)
198
+ return 'none';
199
+ return rows.every((r) => /^[0-9a-f]{64}$/.test(String((0, tables_1.col)(r, 'id') ?? ''))) ? 'sha256-hex' : 'none';
200
+ }
201
+ /** A bytes column from a dump: `\x…` hex (Postgres), plain hex, or base64. */
202
+ function bytesOf(v) {
203
+ if (Buffer.isBuffer(v))
204
+ return v;
205
+ const s = (0, tables_1.text)(v);
206
+ if (!s)
207
+ return null;
208
+ if (/^\\x[0-9a-f]*$/i.test(s))
209
+ return Buffer.from(s.slice(2), 'hex');
210
+ if (/^([0-9a-f]{2})+$/i.test(s) && s.length >= 32)
211
+ return Buffer.from(s, 'hex');
212
+ if (/^[A-Za-z0-9+/_-]+={0,2}$/.test(s))
213
+ return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
214
+ return null;
215
+ }
216
+ /** The guide's `encrypt()`: iv(16) ‖ ciphertext ‖ tag(16), AES-128-GCM (AES-256 for a 32-byte key). */
217
+ function decryptGuideValue(v, key) {
218
+ const data = bytesOf(v);
219
+ if (!data || data.length < 33 || (key.length !== 16 && key.length !== 32))
220
+ return null;
221
+ try {
222
+ const decipher = (0, node_crypto_1.createDecipheriv)(key.length === 16 ? 'aes-128-gcm' : 'aes-256-gcm', key, data.subarray(0, 16));
223
+ decipher.setAuthTag(data.subarray(data.length - 16));
224
+ return Buffer.concat([decipher.update(data.subarray(16, data.length - 16)), decipher.final()]);
225
+ }
226
+ catch {
227
+ return null;
228
+ }
229
+ }
230
+ const B32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
231
+ function base32(data) {
232
+ let bits = 0;
233
+ let value = 0;
234
+ let out = '';
235
+ for (const byte of data) {
236
+ value = (value << 8) | byte;
237
+ bits += 8;
238
+ while (bits >= 5) {
239
+ out += B32[(value >>> (bits - 5)) & 31];
240
+ bits -= 5;
241
+ }
242
+ }
243
+ if (bits > 0)
244
+ out += B32[(value << (5 - bits)) & 31];
245
+ return out;
246
+ }
247
+ /**
248
+ * An uncompressed SEC1 P-256 key (0x04 ‖ x ‖ y) as a COSE_Key:
249
+ * {1: 2 (EC2), 3: -7 (ES256), -1: 1 (P-256), -2: x, -3: y}, CBOR-encoded.
250
+ */
251
+ function coseFromSec1(key) {
252
+ if (!key || key.length !== 65 || key[0] !== 0x04)
253
+ return null;
254
+ const x = key.subarray(1, 33);
255
+ const y = key.subarray(33, 65);
256
+ return Buffer.concat([
257
+ Buffer.from([0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20]),
258
+ x,
259
+ Buffer.from([0x22, 0x58, 0x20]),
260
+ y,
261
+ ]);
262
+ }
263
+ //# sourceMappingURL=lucia.js.map