diff --git a/packages/cli/core/src/commands/auth/token.spec.ts b/packages/cli/core/src/commands/auth/token.spec.ts index 725a1b2842..4dc0fc20c1 100644 --- a/packages/cli/core/src/commands/auth/token.spec.ts +++ b/packages/cli/core/src/commands/auth/token.spec.ts @@ -8,6 +8,7 @@ import {test} from '@oclif/test'; import {Config} from '@coveo/cli-commons/config/config'; import {AuthenticatedClient} from '@coveo/cli-commons/platform/authenticatedClient'; import {PlatformEnvironment} from '@coveo/cli-commons/platform/environment'; +import {CliUx} from '@oclif/core'; const mockedConfig = jest.mocked(Config); const mockedAuthenticatedClient = jest.mocked(AuthenticatedClient); @@ -68,7 +69,8 @@ describe('auth:token', () => { test .stdout() .stderr() - .command(['auth:token', '-e', environment, '-t', 'someToken']) + .stub(CliUx.ux, 'prompt', () => async () => 'someToken') + .command(['auth:token', '-e', environment]) .it(`writes the -e=${environment} flag to the configuration`, () => { expect(mockConfigSet).toHaveBeenCalledWith('environment', environment); }); @@ -78,7 +80,8 @@ describe('auth:token', () => { test .stdout() .stderr() - .command(['auth:token', '-r', region, '-t', 'someToken']) + .stub(CliUx.ux, 'prompt', () => async () => 'someToken') + .command(['auth:token', '-r', region]) .it(`writes the -r=${region} flag and configuration`, () => { expect(mockConfigSet).toHaveBeenCalledWith( 'region', @@ -91,7 +94,8 @@ describe('auth:token', () => { test .stdout() .stderr() - .command(['auth:token', '-t', 'this-is-the-token']) + .stub(CliUx.ux, 'prompt', () => async () => 'this-is-the-token') + .command(['auth:token']) .it('save token from oauth service', () => { expect(mockConfigSet).toHaveBeenCalledWith( 'accessToken', @@ -101,20 +105,14 @@ describe('auth:token', () => { }); }); - test - .stdout() - .stderr() - .command(['auth:token']) - .exit(2) - .it('fails when the token flag is not set'); - test .stdout() .stderr() .do(() => { mockGetHasAccessToOrg.mockReturnValueOnce(Promise.resolve(true)); }) - .command(['auth:token', '-t', 'some-token']) + .stub(CliUx.ux, 'prompt', () => async () => 'some-token') + .command(['auth:token']) .it( 'succeed when the organization and the token flags are valid', (ctx) => { @@ -130,7 +128,8 @@ describe('auth:token', () => { }) .stdout() .stderr() - .command(['auth:token', '-t', 'some-token']) + .stub(CliUx.ux, 'prompt', () => async () => 'some-token') + .command(['auth:token']) .it( 'find the org associated with the token and saves it in the config', () => { diff --git a/packages/cli/core/src/commands/auth/token.ts b/packages/cli/core/src/commands/auth/token.ts index cfed0fe1bc..d691c34202 100644 --- a/packages/cli/core/src/commands/auth/token.ts +++ b/packages/cli/core/src/commands/auth/token.ts @@ -1,5 +1,5 @@ import {CLICommand} from '@coveo/cli-commons/command/cliCommand'; -import {Flags} from '@oclif/core'; +import {CliUx, Flags} from '@oclif/core'; import {Config} from '@coveo/cli-commons/config/config'; import {AuthenticatedClient} from '@coveo/cli-commons/platform/authenticatedClient'; import {PlatformEnvironment} from '@coveo/cli-commons/platform/environment'; @@ -7,6 +7,9 @@ import {Region} from '@coveo/platform-client'; import {withEnvironment, withRegion} from '../../lib/flags/platformCommonFlags'; import {Trackable} from '@coveo/cli-commons/preconditions/trackable'; import {formatOrgId} from '@coveo/cli-commons/utils/ux'; +import {readFile} from 'fs'; +import {} from 'readline'; +import {readFromStdinWithTimeout} from '../../lib/utils/process'; export default class Token extends CLICommand { private configuration!: Config; @@ -18,12 +21,11 @@ export default class Token extends CLICommand { public static flags = { ...withRegion(), ...withEnvironment(), - token: Flags.string({ - char: 't', + stdin: Flags.boolean({ + char: 's', description: - 'The API-Key that shall be used to authenticate you to the organization. See .', - required: true, - helpValue: 'xxx-api-key', + 'Read the token from stdin. Default to true when running in a CI environment.', + default: process.env.CI === 'true', }), }; @@ -52,7 +54,14 @@ export default class Token extends CLICommand { private async saveToken() { const {flags} = await this.parse(Token); - this.configuration.set('accessToken', flags.token); + + const tok = flags.stdin + ? await readFromStdinWithTimeout(1000) + : await CliUx.ux.prompt('Enter your access token: ', { + type: 'hide', + }); + + this.configuration.set('accessToken', tok); this.configuration.set('anonymous', true); } diff --git a/packages/cli/core/src/lib/utils/process.ts b/packages/cli/core/src/lib/utils/process.ts index 14743ac98f..8f413fcf33 100644 --- a/packages/cli/core/src/lib/utils/process.ts +++ b/packages/cli/core/src/lib/utils/process.ts @@ -94,3 +94,20 @@ export const handleForkedProcess = (subprocess: ChildProcess) => { }); }); }; + +export const readFromStdinWithTimeout = ( + timeoutMs: number +): Promise => { + return new Promise(async (resolve, reject) => { + setTimeout(() => { + reject(`Read stdin timeout after ${timeoutMs}ms`); + }, timeoutMs); + const chunks: Buffer[] = []; + + for await (const chunk of process.stdin) { + chunks.push(chunk); + } + + resolve(Buffer.concat(chunks).toString('utf-8')); + }); +};