iterate 0.2.0 → 0.2.2
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.
- package/README.md +3 -3
- package/bin/iterate.js +81 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ Initial setup (writes auth + launcher config):
|
|
|
31
31
|
npx iterate setup \
|
|
32
32
|
--base-url https://dev-yourname-os.dev.iterate.com \
|
|
33
33
|
--admin-password-env-var-name SERVICE_AUTH_TOKEN \
|
|
34
|
-
--user-
|
|
34
|
+
--user-email dev-yourname@iterate.com \
|
|
35
35
|
--repo-path managed \
|
|
36
36
|
--auto-install true \
|
|
37
37
|
--scope global
|
|
@@ -72,7 +72,7 @@ Config shape:
|
|
|
72
72
|
"/absolute/workspace/path": {
|
|
73
73
|
"baseUrl": "https://dev-yourname-os.dev.iterate.com",
|
|
74
74
|
"adminPasswordEnvVarName": "SERVICE_AUTH_TOKEN",
|
|
75
|
-
"
|
|
75
|
+
"userEmail": "dev-yourname@iterate.com",
|
|
76
76
|
"repoPath": "/absolute/path/to/iterate",
|
|
77
77
|
"autoInstall": false
|
|
78
78
|
}
|
|
@@ -116,7 +116,7 @@ You can pin explicitly:
|
|
|
116
116
|
npx iterate setup \
|
|
117
117
|
--base-url https://dev-yourname-os.dev.iterate.com \
|
|
118
118
|
--admin-password-env-var-name SERVICE_AUTH_TOKEN \
|
|
119
|
-
--user-
|
|
119
|
+
--user-email dev-yourname@iterate.com \
|
|
120
120
|
--repo-path local \
|
|
121
121
|
--auto-install false \
|
|
122
122
|
--scope workspace
|
package/bin/iterate.js
CHANGED
|
@@ -92,7 +92,7 @@ const SetupInput = z.object({
|
|
|
92
92
|
.string()
|
|
93
93
|
.describe(`Base URL for os API (for example https://dev-yourname-os.dev.iterate.com)`),
|
|
94
94
|
adminPasswordEnvVarName: z.string().describe("Env var name containing admin password"),
|
|
95
|
-
|
|
95
|
+
userEmail: z.string().describe("User email to impersonate for os calls"),
|
|
96
96
|
repoPath: z.string().describe("Path to iterate checkout (or 'local' / 'managed' shortcuts)"),
|
|
97
97
|
autoInstall: z.boolean().describe("Auto install dependencies when missing"),
|
|
98
98
|
scope: z.enum(["workspace", "global"]).describe("Where to store launcher config"),
|
|
@@ -101,7 +101,7 @@ const SetupInput = z.object({
|
|
|
101
101
|
const AuthConfig = z.object({
|
|
102
102
|
baseUrl: z.string(),
|
|
103
103
|
adminPasswordEnvVarName: z.string(),
|
|
104
|
-
|
|
104
|
+
userEmail: z.string(),
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
/** @param {string} message */
|
|
@@ -350,6 +350,77 @@ const setCookiesToCookieHeader = (setCookies) => {
|
|
|
350
350
|
return [...byName.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
|
|
351
351
|
};
|
|
352
352
|
|
|
353
|
+
const impersonationUserIdCache = new Map();
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* @param {{
|
|
357
|
+
* superadminAuthClient: any;
|
|
358
|
+
* userEmail: string;
|
|
359
|
+
* baseUrl: string;
|
|
360
|
+
* }} options
|
|
361
|
+
*/
|
|
362
|
+
const resolveImpersonationUserId = async ({ superadminAuthClient, userEmail, baseUrl }) => {
|
|
363
|
+
const normalizedEmail = userEmail.trim().toLowerCase();
|
|
364
|
+
const cacheKey = `${baseUrl}::${normalizedEmail}`;
|
|
365
|
+
const cachedUserId = impersonationUserIdCache.get(cacheKey);
|
|
366
|
+
if (cachedUserId) {
|
|
367
|
+
return cachedUserId;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** @type {any[]} */
|
|
371
|
+
let users = [];
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
const result = await superadminAuthClient.admin.listUsers({
|
|
375
|
+
query: {
|
|
376
|
+
filterField: "email",
|
|
377
|
+
filterOperator: "eq",
|
|
378
|
+
filterValue: normalizedEmail,
|
|
379
|
+
limit: 10,
|
|
380
|
+
},
|
|
381
|
+
fetchOptions: {
|
|
382
|
+
throw: true,
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
users = Array.isArray(result?.users) ? result.users : [];
|
|
386
|
+
} catch {
|
|
387
|
+
const result = await superadminAuthClient.admin.listUsers({
|
|
388
|
+
query: {
|
|
389
|
+
searchField: "email",
|
|
390
|
+
searchOperator: "contains",
|
|
391
|
+
searchValue: normalizedEmail,
|
|
392
|
+
limit: 100,
|
|
393
|
+
},
|
|
394
|
+
fetchOptions: {
|
|
395
|
+
throw: true,
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
users = Array.isArray(result?.users) ? result.users : [];
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const exactMatches = users.filter(
|
|
402
|
+
(user) =>
|
|
403
|
+
user &&
|
|
404
|
+
typeof user === "object" &&
|
|
405
|
+
"email" in user &&
|
|
406
|
+
typeof user.email === "string" &&
|
|
407
|
+
user.email.toLowerCase() === normalizedEmail &&
|
|
408
|
+
"id" in user &&
|
|
409
|
+
typeof user.id === "string",
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
if (exactMatches.length === 0) {
|
|
413
|
+
throw new Error(`No user found with email ${userEmail}`);
|
|
414
|
+
}
|
|
415
|
+
if (exactMatches.length > 1) {
|
|
416
|
+
throw new Error(`Multiple users found with email ${userEmail}`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const resolvedUserId = exactMatches[0].id;
|
|
420
|
+
impersonationUserIdCache.set(cacheKey, resolvedUserId);
|
|
421
|
+
return resolvedUserId;
|
|
422
|
+
};
|
|
423
|
+
|
|
353
424
|
/** @param {z.infer<typeof AuthConfig>} authConfig */
|
|
354
425
|
const authDance = async (authConfig) => {
|
|
355
426
|
let superadminSetCookie;
|
|
@@ -387,9 +458,15 @@ const authDance = async (authConfig) => {
|
|
|
387
458
|
plugins: [adminClient()],
|
|
388
459
|
});
|
|
389
460
|
|
|
461
|
+
const userId = await resolveImpersonationUserId({
|
|
462
|
+
superadminAuthClient,
|
|
463
|
+
userEmail: authConfig.userEmail,
|
|
464
|
+
baseUrl: authConfig.baseUrl,
|
|
465
|
+
});
|
|
466
|
+
|
|
390
467
|
let impersonateSetCookie;
|
|
391
468
|
await superadminAuthClient.admin.impersonateUser({
|
|
392
|
-
userId
|
|
469
|
+
userId,
|
|
393
470
|
fetchOptions: {
|
|
394
471
|
throw: true,
|
|
395
472
|
onResponse: (ctx) => {
|
|
@@ -607,7 +684,7 @@ const launcherProcedures = {
|
|
|
607
684
|
workspacePatch: {
|
|
608
685
|
baseUrl: input.baseUrl,
|
|
609
686
|
adminPasswordEnvVarName: input.adminPasswordEnvVarName,
|
|
610
|
-
|
|
687
|
+
userEmail: input.userEmail,
|
|
611
688
|
},
|
|
612
689
|
scope: input.scope,
|
|
613
690
|
workspacePath: process.cwd(),
|