instant-cli 1.0.21-branch-cli-codex.25186296431.1 → 1.0.21-branch-cli-codex.25187076703.1
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/.turbo/turbo-build.log +1 -1
- package/__tests__/authClientUpdate.test.ts +174 -3
- package/dist/commands/auth/client/update.d.ts.map +1 -1
- package/dist/commands/auth/client/update.js +95 -61
- package/dist/commands/auth/client/update.js.map +1 -1
- package/dist/lib/oauth.d.ts +49 -8
- package/dist/lib/oauth.d.ts.map +1 -1
- package/dist/lib/oauth.js +25 -1
- package/dist/lib/oauth.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/auth/client/update.ts +124 -78
- package/src/lib/oauth.ts +36 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> instant-cli@1.0.21-branch-cli-codex.
|
|
2
|
+
> instant-cli@1.0.21-branch-cli-codex.25187076703.1 build /home/runner/work/instant/instant/client/packages/cli
|
|
3
3
|
> rm -rf dist; tsc -p tsconfig.build.json
|
|
4
4
|
|
|
@@ -4,6 +4,7 @@ import { NodeContext } from '@effect/platform-node';
|
|
|
4
4
|
import { GlobalOpts } from '../src/context/globalOpts.ts';
|
|
5
5
|
import { CurrentApp } from '../src/context/currentApp.ts';
|
|
6
6
|
import { InstantHttpAuthed } from '../src/lib/http.ts';
|
|
7
|
+
import { BadArgsError } from '../src/errors.ts';
|
|
7
8
|
|
|
8
9
|
// Prevent src/index.ts side-effect (program.parse) from running.
|
|
9
10
|
vi.mock('../src/index.ts', () => ({}));
|
|
@@ -17,7 +18,10 @@ vi.mock('../src/ui/lib.ts', async (importOriginal) => {
|
|
|
17
18
|
...orig,
|
|
18
19
|
renderUnwrap: (prompt: any) => {
|
|
19
20
|
prompts.push(prompt);
|
|
20
|
-
|
|
21
|
+
const value = Array.isArray(mockPromptReturn)
|
|
22
|
+
? mockPromptReturn.shift()
|
|
23
|
+
: mockPromptReturn;
|
|
24
|
+
return Promise.resolve(value);
|
|
21
25
|
},
|
|
22
26
|
};
|
|
23
27
|
});
|
|
@@ -27,6 +31,7 @@ let mockClients: any[] = [];
|
|
|
27
31
|
const providers = [
|
|
28
32
|
{ id: 'prov-google', provider_name: 'google' },
|
|
29
33
|
{ id: 'prov-github', provider_name: 'github' },
|
|
34
|
+
{ id: 'prov-apple', provider_name: 'apple' },
|
|
30
35
|
{ id: 'prov-clerk', provider_name: 'clerk' },
|
|
31
36
|
{ id: 'prov-firebase', provider_name: 'firebase' },
|
|
32
37
|
];
|
|
@@ -37,6 +42,34 @@ vi.mock('../src/lib/oauth.ts', () => ({
|
|
|
37
42
|
oauth_service_providers: providers,
|
|
38
43
|
oauth_clients: mockClients,
|
|
39
44
|
}),
|
|
45
|
+
findClientByIdOrName: ({ id, name }: { id?: string; name?: string }) =>
|
|
46
|
+
Effect.gen(function* () {
|
|
47
|
+
if (id && name) {
|
|
48
|
+
return yield* BadArgsError.make({
|
|
49
|
+
message: 'Cannot specify both --id and --name',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (!id && !name) {
|
|
53
|
+
return yield* BadArgsError.make({
|
|
54
|
+
message: 'Must specify --id or --name',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const client = id
|
|
58
|
+
? mockClients.find((entry) => entry.id === id)
|
|
59
|
+
: mockClients.find((entry) => entry.client_name === name);
|
|
60
|
+
if (!client) {
|
|
61
|
+
return yield* BadArgsError.make({
|
|
62
|
+
message: `OAuth client not found: ${id ?? name}`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
client,
|
|
67
|
+
auth: {
|
|
68
|
+
oauth_service_providers: providers,
|
|
69
|
+
oauth_clients: mockClients,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}),
|
|
40
73
|
updateOAuthClient: (params: any) => {
|
|
41
74
|
updatedClients.push(params);
|
|
42
75
|
const client = mockClients.find((c) => c.id === params.oauthClientId);
|
|
@@ -109,6 +142,16 @@ beforeEach(() => {
|
|
|
109
142
|
client_name: 'github',
|
|
110
143
|
client_id: 'old-gh-id',
|
|
111
144
|
},
|
|
145
|
+
{
|
|
146
|
+
id: 'apple',
|
|
147
|
+
provider_id: 'prov-apple',
|
|
148
|
+
client_name: 'apple',
|
|
149
|
+
client_id: 'old.apple.service',
|
|
150
|
+
meta: {
|
|
151
|
+
teamId: 'OLDTEAM',
|
|
152
|
+
keyId: 'OLDKEY',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
112
155
|
{
|
|
113
156
|
id: 'clerk',
|
|
114
157
|
provider_id: 'prov-clerk',
|
|
@@ -165,13 +208,47 @@ describe('google', () => {
|
|
|
165
208
|
expect(logs.join('\n')).toContain('Credentials: Instant dev credentials');
|
|
166
209
|
});
|
|
167
210
|
|
|
211
|
+
test('rejects dev credentials with custom credential flags', async () => {
|
|
212
|
+
await run(
|
|
213
|
+
{
|
|
214
|
+
name: 'google-web',
|
|
215
|
+
'dev-credentials': true,
|
|
216
|
+
'client-id': 'new-google-id',
|
|
217
|
+
},
|
|
218
|
+
{ yes: true },
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
expect(logs.join('\n')).toContain(
|
|
222
|
+
'--dev-credentials cannot be combined with --client-id',
|
|
223
|
+
);
|
|
224
|
+
expect(updatedClients).toHaveLength(0);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('updates redirect URI only', async () => {
|
|
228
|
+
await run(
|
|
229
|
+
{
|
|
230
|
+
name: 'google-web',
|
|
231
|
+
'custom-redirect-uri': 'https://example.com/oauth/callback',
|
|
232
|
+
},
|
|
233
|
+
{ yes: true },
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
expect(updatedClients).toHaveLength(1);
|
|
237
|
+
expect(updatedClients[0]).toMatchObject({
|
|
238
|
+
oauthClientId: 'google-web',
|
|
239
|
+
redirectTo: 'https://example.com/oauth/callback',
|
|
240
|
+
});
|
|
241
|
+
expect(updatedClients[0].clientId).toBeUndefined();
|
|
242
|
+
expect(updatedClients[0].clientSecret).toBeUndefined();
|
|
243
|
+
});
|
|
244
|
+
|
|
168
245
|
test('interactive Google web update can select dev credentials', async () => {
|
|
169
|
-
mockPromptReturn = 'dev';
|
|
246
|
+
mockPromptReturn = 'dev-credentials';
|
|
170
247
|
await run({ name: 'google-web' }, { yes: false });
|
|
171
248
|
|
|
172
249
|
expect(prompts).toHaveLength(1);
|
|
173
250
|
expect((prompts[0] as any).params.promptText).toBe(
|
|
174
|
-
'
|
|
251
|
+
'What do you want to update?',
|
|
175
252
|
);
|
|
176
253
|
expect(updatedClients[0]).toMatchObject({
|
|
177
254
|
oauthClientId: 'google-web',
|
|
@@ -214,6 +291,60 @@ describe('provider credential updates', () => {
|
|
|
214
291
|
expect(updatedClients[0].clientId).toBeUndefined();
|
|
215
292
|
});
|
|
216
293
|
|
|
294
|
+
test('interactive GitHub update can select redirect URI', async () => {
|
|
295
|
+
mockPromptReturn = ['redirect', 'https://example.com/oauth/callback'];
|
|
296
|
+
|
|
297
|
+
await run({ name: 'github' }, { yes: false });
|
|
298
|
+
|
|
299
|
+
expect(prompts).toHaveLength(2);
|
|
300
|
+
expect((prompts[0] as any).params.promptText).toBe(
|
|
301
|
+
'What do you want to update?',
|
|
302
|
+
);
|
|
303
|
+
expect(updatedClients).toHaveLength(1);
|
|
304
|
+
expect(updatedClients[0]).toMatchObject({
|
|
305
|
+
oauthClientId: 'github',
|
|
306
|
+
redirectTo: 'https://example.com/oauth/callback',
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test('updates Apple Services ID only', async () => {
|
|
311
|
+
await run(
|
|
312
|
+
{
|
|
313
|
+
name: 'apple',
|
|
314
|
+
'services-id': 'new.apple.service',
|
|
315
|
+
},
|
|
316
|
+
{ yes: true },
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
expect(updatedClients).toHaveLength(1);
|
|
320
|
+
expect(updatedClients[0]).toMatchObject({
|
|
321
|
+
oauthClientId: 'apple',
|
|
322
|
+
clientId: 'new.apple.service',
|
|
323
|
+
});
|
|
324
|
+
expect(updatedClients[0].meta).toBeUndefined();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
test('updates Apple team and key metadata', async () => {
|
|
328
|
+
await run(
|
|
329
|
+
{
|
|
330
|
+
name: 'apple',
|
|
331
|
+
'team-id': 'TEAM123',
|
|
332
|
+
'key-id': 'KEY456',
|
|
333
|
+
},
|
|
334
|
+
{ yes: true },
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
expect(updatedClients).toHaveLength(1);
|
|
338
|
+
expect(updatedClients[0]).toMatchObject({
|
|
339
|
+
oauthClientId: 'apple',
|
|
340
|
+
meta: {
|
|
341
|
+
teamId: 'TEAM123',
|
|
342
|
+
keyId: 'KEY456',
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
expect(updatedClients[0].clientId).toBeUndefined();
|
|
346
|
+
});
|
|
347
|
+
|
|
217
348
|
test('updates Clerk publishable key and discovery endpoint', async () => {
|
|
218
349
|
await run(
|
|
219
350
|
{
|
|
@@ -252,6 +383,19 @@ describe('provider credential updates', () => {
|
|
|
252
383
|
'https://securetoken.google.com/my-app-123/.well-known/openid-configuration',
|
|
253
384
|
});
|
|
254
385
|
});
|
|
386
|
+
|
|
387
|
+
test('rejects invalid Firebase project ID', async () => {
|
|
388
|
+
await run(
|
|
389
|
+
{
|
|
390
|
+
name: 'firebase',
|
|
391
|
+
'project-id': 'BAD',
|
|
392
|
+
},
|
|
393
|
+
{ yes: true },
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
expect(logs.join('\n')).toContain('Invalid Firebase project ID');
|
|
397
|
+
expect(updatedClients).toHaveLength(0);
|
|
398
|
+
});
|
|
255
399
|
});
|
|
256
400
|
|
|
257
401
|
describe('--yes validation', () => {
|
|
@@ -268,4 +412,31 @@ describe('--yes validation', () => {
|
|
|
268
412
|
);
|
|
269
413
|
expect(updatedClients).toHaveLength(0);
|
|
270
414
|
});
|
|
415
|
+
|
|
416
|
+
test('rejects both id and name', async () => {
|
|
417
|
+
await run(
|
|
418
|
+
{
|
|
419
|
+
id: 'github',
|
|
420
|
+
name: 'github',
|
|
421
|
+
'client-secret': 'new-gh-secret',
|
|
422
|
+
},
|
|
423
|
+
{ yes: true },
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
expect(logs.join('\n')).toContain('Cannot specify both --id and --name');
|
|
427
|
+
expect(updatedClients).toHaveLength(0);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
test('rejects unknown client name', async () => {
|
|
431
|
+
await run(
|
|
432
|
+
{
|
|
433
|
+
name: 'unknown',
|
|
434
|
+
'client-secret': 'new-gh-secret',
|
|
435
|
+
},
|
|
436
|
+
{ yes: true },
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
expect(logs.join('\n')).toContain('OAuth client not found');
|
|
440
|
+
expect(updatedClients).toHaveLength(0);
|
|
441
|
+
});
|
|
271
442
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/commands/auth/client/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/commands/auth/client/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AA6rB5D,eAAO,MAAM,mBAAmB;;;;;ieAqE/B,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { FileSystem } from '@effect/platform';
|
|
|
3
3
|
import { BadArgsError } from "../../../errors.js";
|
|
4
4
|
import { GlobalOpts } from "../../../context/globalOpts.js";
|
|
5
5
|
import { optOrPrompt, runUIEffect, validateRequired } from "../../../lib/ui.js";
|
|
6
|
-
import { getAppsAuth, updateOAuthClient } from "../../../lib/oauth.js";
|
|
6
|
+
import { findClientByIdOrName, getAppsAuth, updateOAuthClient, } from "../../../lib/oauth.js";
|
|
7
7
|
import { UI } from "../../../ui/index.js";
|
|
8
8
|
import { DEFAULT_OAUTH_CALLBACK_URL } from '@instantdb/platform';
|
|
9
9
|
import chalk from 'chalk';
|
|
@@ -48,22 +48,24 @@ const clientSecretPrompt = (provider) => ({
|
|
|
48
48
|
UI.modifiers.dimOnComplete,
|
|
49
49
|
]),
|
|
50
50
|
});
|
|
51
|
-
const
|
|
51
|
+
const makeRedirectPrompt = (heading) => ({
|
|
52
52
|
prompt: '',
|
|
53
53
|
placeholder: 'https://yoursite.com/oauth/callback',
|
|
54
54
|
modifyOutput: UI.modifiers.piped([
|
|
55
55
|
(output, status) => {
|
|
56
56
|
if (status === 'idle') {
|
|
57
|
-
return (`\
|
|
57
|
+
return (`\n${heading}
|
|
58
58
|
${chalk.dim('With a custom redirect URI, users will see "Redirecting to yoursite.com..." for a more branded experience.')}
|
|
59
59
|
${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all query parameters preserved.`)}\n\n` +
|
|
60
60
|
output.replace(/^\n/, ''));
|
|
61
61
|
}
|
|
62
|
-
return `\
|
|
62
|
+
return `\n${heading}\n${output.replace(/^\n/, '')}`;
|
|
63
63
|
},
|
|
64
64
|
UI.modifiers.dimOnComplete,
|
|
65
65
|
]),
|
|
66
|
-
};
|
|
66
|
+
});
|
|
67
|
+
const redirectPrompt = makeRedirectPrompt('Custom redirect URI (optional):');
|
|
68
|
+
const newRedirectPrompt = makeRedirectPrompt('New redirect URI:');
|
|
67
69
|
const readPrivateKeyFile = Effect.fn('readPrivateKeyFile')(function* (path) {
|
|
68
70
|
const fs = yield* FileSystem.FileSystem;
|
|
69
71
|
const normalizedPath = process.platform === 'win32' ? path : path.replace(/\\(.)/g, '$1');
|
|
@@ -123,26 +125,11 @@ const resolveClient = Effect.fn(function* (params) {
|
|
|
123
125
|
modifyOutput: UI.modifiers.piped([UI.modifiers.dimOnComplete]),
|
|
124
126
|
})).pipe(Effect.catchTag('UIError', (e) => BadArgsError.make({ message: `UI error: ${e.message}` })));
|
|
125
127
|
});
|
|
126
|
-
const
|
|
128
|
+
const selectUpdateAction = Effect.fn(function* (options) {
|
|
127
129
|
return yield* runUIEffect(new UI.Select({
|
|
128
|
-
options
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
chalk.dim(' (client ID and secret from Google Console)'),
|
|
132
|
-
value: 'custom',
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
label: 'Use dev credentials' +
|
|
136
|
-
chalk.dim(' (works on localhost and Expo, no Google setup)'),
|
|
137
|
-
value: 'dev',
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
promptText: 'Select Google credential mode:',
|
|
141
|
-
modifyOutput: UI.modifiers.piped([
|
|
142
|
-
UI.modifiers.topPadding,
|
|
143
|
-
UI.modifiers.dimOnComplete,
|
|
144
|
-
]),
|
|
145
|
-
defaultValue: 'custom',
|
|
130
|
+
options,
|
|
131
|
+
promptText: 'What do you want to update?',
|
|
132
|
+
modifyOutput: UI.modifiers.piped([UI.modifiers.dimOnComplete]),
|
|
146
133
|
})).pipe(Effect.catchTag('UIError', (e) => BadArgsError.make({ message: `UI error: ${e.message}` })));
|
|
147
134
|
});
|
|
148
135
|
const updateGoogleToDevCredentials = Effect.fn(function* (client) {
|
|
@@ -162,6 +149,7 @@ const updateGoogleToDevCredentials = Effect.fn(function* (client) {
|
|
|
162
149
|
});
|
|
163
150
|
const handleGoogleUpdate = Effect.fn(function* (opts, client) {
|
|
164
151
|
const { yes } = yield* GlobalOpts;
|
|
152
|
+
const consoleUrl = link('https://console.developers.google.com/apis/credentials');
|
|
165
153
|
const appType = metaString(client, 'appType');
|
|
166
154
|
const isWeb = appType === 'web' || appType === undefined;
|
|
167
155
|
const devCredentialsFlag = isTrueFlag(getFlag(opts, 'dev-credentials'));
|
|
@@ -202,28 +190,59 @@ const handleGoogleUpdate = Effect.fn(function* (opts, client) {
|
|
|
202
190
|
message: 'Must specify at least one of --client-id, --client-secret, --custom-redirect-uri, or --dev-credentials.',
|
|
203
191
|
});
|
|
204
192
|
}
|
|
205
|
-
const selectedMode = isWeb && !hasAnyUpdateFlag && !yes
|
|
206
|
-
? yield* selectGoogleCredentialMode()
|
|
207
|
-
: 'custom';
|
|
208
|
-
if (selectedMode === 'dev') {
|
|
209
|
-
return yield* updateGoogleToDevCredentials(client);
|
|
210
|
-
}
|
|
211
|
-
const promptAll = !hasAnyUpdateFlag && !yes;
|
|
212
193
|
const switchingFromShared = Boolean(client.use_shared_credentials);
|
|
194
|
+
if (!hasAnyUpdateFlag && !yes) {
|
|
195
|
+
yield* Effect.log(`\nCurrent mode: ${switchingFromShared
|
|
196
|
+
? chalk.bold('Instant dev credentials')
|
|
197
|
+
: 'custom credentials'}`);
|
|
198
|
+
if (!switchingFromShared) {
|
|
199
|
+
const action = yield* selectUpdateAction([
|
|
200
|
+
{ label: 'Rotate credentials', value: 'rotate' },
|
|
201
|
+
{
|
|
202
|
+
label: 'Switch to Instant dev credentials' +
|
|
203
|
+
chalk.dim(' (localhost and Expo, no Google setup)'),
|
|
204
|
+
value: 'dev-credentials',
|
|
205
|
+
},
|
|
206
|
+
{ label: 'Update redirect URI', value: 'redirect' },
|
|
207
|
+
]);
|
|
208
|
+
if (action === 'dev-credentials') {
|
|
209
|
+
return yield* updateGoogleToDevCredentials(client);
|
|
210
|
+
}
|
|
211
|
+
if (action === 'redirect') {
|
|
212
|
+
const redirectTo = yield* promptFlag(opts, 'custom-redirect-uri', {
|
|
213
|
+
promptIf: true,
|
|
214
|
+
required: true,
|
|
215
|
+
prompt: newRedirectPrompt,
|
|
216
|
+
});
|
|
217
|
+
const response = yield* updateOAuthClient({
|
|
218
|
+
oauthClientId: client.id,
|
|
219
|
+
redirectTo,
|
|
220
|
+
});
|
|
221
|
+
yield* Effect.log(boxen([
|
|
222
|
+
`Google OAuth client updated: ${response.client.client_name}`,
|
|
223
|
+
`ID: ${response.client.id}`,
|
|
224
|
+
`Redirect URI: ${redirectTo}`,
|
|
225
|
+
].join('\n'), { dimBorder: true, padding: { right: 1, left: 1 } }));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const promptCredentials = !hasAnyUpdateFlag && !yes;
|
|
213
231
|
const clientId = yield* promptFlag(opts, 'client-id', {
|
|
214
|
-
promptIf:
|
|
215
|
-
required:
|
|
216
|
-
prompt: clientIdPrompt(
|
|
232
|
+
promptIf: promptCredentials || (switchingFromShared && !hasFlag(opts, 'client-id')),
|
|
233
|
+
required: promptCredentials || switchingFromShared,
|
|
234
|
+
prompt: clientIdPrompt(consoleUrl),
|
|
217
235
|
});
|
|
218
236
|
const clientSecret = yield* promptFlag(opts, 'client-secret', {
|
|
219
237
|
promptIf: isWeb &&
|
|
220
|
-
(
|
|
221
|
-
|
|
222
|
-
|
|
238
|
+
(promptCredentials ||
|
|
239
|
+
(switchingFromShared && !hasFlag(opts, 'client-secret'))),
|
|
240
|
+
required: isWeb && (promptCredentials || switchingFromShared),
|
|
241
|
+
prompt: clientSecretPrompt(consoleUrl),
|
|
223
242
|
});
|
|
224
243
|
const customRedirectUri = isWeb
|
|
225
244
|
? yield* promptFlag(opts, 'custom-redirect-uri', {
|
|
226
|
-
promptIf:
|
|
245
|
+
promptIf: switchingFromShared && promptCredentials,
|
|
227
246
|
required: false,
|
|
228
247
|
prompt: redirectPrompt,
|
|
229
248
|
})
|
|
@@ -266,21 +285,30 @@ const handleClientIdSecretUpdate = Effect.fn(function* (params) {
|
|
|
266
285
|
message: 'Must specify at least one of --client-id, --client-secret, or --custom-redirect-uri.',
|
|
267
286
|
});
|
|
268
287
|
}
|
|
269
|
-
|
|
288
|
+
let promptCredentials = false;
|
|
289
|
+
let promptRedirect = false;
|
|
290
|
+
if (!hasAnyUpdateFlag && !yes) {
|
|
291
|
+
const action = yield* selectUpdateAction([
|
|
292
|
+
{ label: 'Rotate credentials', value: 'rotate' },
|
|
293
|
+
{ label: 'Update redirect URI', value: 'redirect' },
|
|
294
|
+
]);
|
|
295
|
+
promptCredentials = action === 'rotate';
|
|
296
|
+
promptRedirect = action === 'redirect';
|
|
297
|
+
}
|
|
270
298
|
const clientId = yield* promptFlag(params.opts, 'client-id', {
|
|
271
|
-
promptIf:
|
|
272
|
-
required:
|
|
299
|
+
promptIf: promptCredentials,
|
|
300
|
+
required: promptCredentials,
|
|
273
301
|
prompt: clientIdPrompt(link(params.providerUrl)),
|
|
274
302
|
});
|
|
275
303
|
const clientSecret = yield* promptFlag(params.opts, 'client-secret', {
|
|
276
|
-
promptIf:
|
|
277
|
-
required:
|
|
304
|
+
promptIf: promptCredentials,
|
|
305
|
+
required: promptCredentials,
|
|
278
306
|
prompt: clientSecretPrompt(link(params.providerUrl)),
|
|
279
307
|
});
|
|
280
308
|
const customRedirectUri = yield* promptFlag(params.opts, 'custom-redirect-uri', {
|
|
281
|
-
promptIf:
|
|
282
|
-
required:
|
|
283
|
-
prompt: redirectPrompt,
|
|
309
|
+
promptIf: promptRedirect,
|
|
310
|
+
required: promptRedirect,
|
|
311
|
+
prompt: promptRedirect ? newRedirectPrompt : redirectPrompt,
|
|
284
312
|
});
|
|
285
313
|
const response = yield* updateOAuthClient({
|
|
286
314
|
oauthClientId: params.client.id,
|
|
@@ -475,42 +503,48 @@ const handleFirebaseUpdate = Effect.fn(function* (opts, client) {
|
|
|
475
503
|
});
|
|
476
504
|
export const authClientUpdateCmd = Effect.fn(function* (opts) {
|
|
477
505
|
const { yes } = yield* GlobalOpts;
|
|
478
|
-
const
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
506
|
+
const id = getFlag(opts, 'id');
|
|
507
|
+
const name = getFlag(opts, 'name');
|
|
508
|
+
const { auth, client } = id || name
|
|
509
|
+
? yield* findClientByIdOrName({ id, name })
|
|
510
|
+
: {
|
|
511
|
+
auth: yield* getAppsAuth(),
|
|
512
|
+
client: undefined,
|
|
513
|
+
};
|
|
514
|
+
const resolvedClient = client ??
|
|
515
|
+
(yield* resolveClient({
|
|
516
|
+
yes,
|
|
517
|
+
clients: (auth.oauth_clients ?? []),
|
|
518
|
+
}));
|
|
519
|
+
const provider = (auth.oauth_service_providers ?? []).find((entry) => entry.id === resolvedClient.provider_id);
|
|
486
520
|
if (!provider) {
|
|
487
521
|
return yield* BadArgsError.make({
|
|
488
|
-
message: `OAuth provider not found for client: ${
|
|
522
|
+
message: `OAuth provider not found for client: ${resolvedClient.client_name}`,
|
|
489
523
|
});
|
|
490
524
|
}
|
|
491
525
|
switch (provider.provider_name) {
|
|
492
526
|
case 'google':
|
|
493
|
-
return yield* handleGoogleUpdate(opts,
|
|
527
|
+
return yield* handleGoogleUpdate(opts, resolvedClient);
|
|
494
528
|
case 'github':
|
|
495
529
|
return yield* handleClientIdSecretUpdate({
|
|
496
530
|
opts,
|
|
497
|
-
client,
|
|
531
|
+
client: resolvedClient,
|
|
498
532
|
providerLabel: 'GitHub',
|
|
499
533
|
providerUrl: 'https://github.com/settings/developers',
|
|
500
534
|
});
|
|
501
535
|
case 'linkedin':
|
|
502
536
|
return yield* handleClientIdSecretUpdate({
|
|
503
537
|
opts,
|
|
504
|
-
client,
|
|
538
|
+
client: resolvedClient,
|
|
505
539
|
providerLabel: 'LinkedIn',
|
|
506
540
|
providerUrl: 'https://www.linkedin.com/developers/apps',
|
|
507
541
|
});
|
|
508
542
|
case 'apple':
|
|
509
|
-
return yield* handleAppleUpdate(opts,
|
|
543
|
+
return yield* handleAppleUpdate(opts, resolvedClient);
|
|
510
544
|
case 'clerk':
|
|
511
|
-
return yield* handleClerkUpdate(opts,
|
|
545
|
+
return yield* handleClerkUpdate(opts, resolvedClient);
|
|
512
546
|
case 'firebase':
|
|
513
|
-
return yield* handleFirebaseUpdate(opts,
|
|
547
|
+
return yield* handleFirebaseUpdate(opts, resolvedClient);
|
|
514
548
|
default:
|
|
515
549
|
return yield* BadArgsError.make({
|
|
516
550
|
message: `Updating ${provider.provider_name} OAuth clients is not supported.`,
|