Skip to content

Commit ab5c455

Browse files
authored
Merge pull request #1461 from salesforcecli/sl/verificationCode
feat: Display message and verificationCode-W-21485176
2 parents 1dac96f + 4615251 commit ab5c455

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

messages/web.login.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,7 @@ Unable to open the browser you specified (%s).
7979
# error.cannotOpenBrowser.actions
8080

8181
- Ensure that %s is installed on your computer. Or specify a different browser using the --browser flag.
82+
83+
# verificationCode
84+
85+
- Verification Code: %s — If prompted, enter this code in your browser window.

src/commands/org/login/web.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { createHash } from 'node:crypto';
1718
import open, { apps, AppName } from 'open';
1819
import { Flags, SfCommand, loglevel } from '@salesforce/sf-plugins-core';
1920
import { AuthFields, AuthInfo, Logger, Messages, OAuth2Config, SfError, WebOAuthServer } from '@salesforce/core';
@@ -24,6 +25,13 @@ Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
2425
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'web.login');
2526
const commonMessages = Messages.loadMessages('@salesforce/plugin-auth', 'messages');
2627

28+
export const CODE_BUILDER_STATE_ENV_VAR = 'CODE_BUILDER_STATE';
29+
30+
export const getVerificationCode = (codeBuilderState: string): string => {
31+
const hash = createHash('sha256').update(codeBuilderState, 'utf8').digest('hex');
32+
return hash.substring(0, 4);
33+
};
34+
2735
export type ExecuteLoginFlowParams = {
2836
oauthConfig: OAuth2Config;
2937
browser?: string;
@@ -112,6 +120,15 @@ export default class LoginWeb extends SfCommand<AuthFields> {
112120
throw new SfError(messages.getMessage('error.headlessWebAuth'));
113121
}
114122

123+
// Display verification code for Code Builder mode if env is set
124+
const env = new Env();
125+
const codeBuilderState = env.getString(CODE_BUILDER_STATE_ENV_VAR);
126+
if (codeBuilderState) {
127+
const verificationCode = getVerificationCode(codeBuilderState);
128+
129+
this.log(messages.getMessage('verificationCode', [verificationCode]));
130+
}
131+
115132
if (await common.shouldExitCommand(flags['no-prompt'])) return {};
116133

117134
// Add ca/eca to already existing auth info.

test/commands/org/login/login.web.test.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@
1717
/* eslint-disable @typescript-eslint/ban-ts-comment */
1818

1919
import { Config } from '@oclif/core';
20-
import { AuthFields, AuthInfo, SfError } from '@salesforce/core';
20+
import { AuthFields, AuthInfo, SfError, Messages } from '@salesforce/core';
2121
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
2222
import { StubbedType, stubInterface, stubMethod } from '@salesforce/ts-sinon';
2323
import { assert, expect } from 'chai';
2424
import { Env } from '@salesforce/kit';
2525
import { SfCommand, Ux } from '@salesforce/sf-plugins-core';
26-
import LoginWeb, { ExecuteLoginFlowParams } from '../../../../src/commands/org/login/web.js';
26+
import LoginWeb, {
27+
ExecuteLoginFlowParams,
28+
CODE_BUILDER_STATE_ENV_VAR,
29+
getVerificationCode,
30+
} from '../../../../src/commands/org/login/web.js';
2731

2832
describe('org:login:web', () => {
33+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
34+
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'web.login');
2935
const $$ = new TestContext();
3036
const testData = new MockTestOrgData();
3137
const config = stubInterface<Config>($$.SANDBOX, {
@@ -302,4 +308,51 @@ describe('org:login:web', () => {
302308
expect(callArgs.clientApp?.username).to.equal('test@example.com');
303309
expect(callArgs.scopes).to.be.undefined;
304310
});
311+
312+
it('should display verification code when CODE_BUILDER_STATE env var is set', async () => {
313+
const codeBuilderState = 'CODE_BUILDER_STATE';
314+
const envStub = $$.SANDBOX.stub(Env.prototype, 'getString');
315+
envStub.withArgs(CODE_BUILDER_STATE_ENV_VAR).returns(codeBuilderState);
316+
envStub.returns(''); // Default for other calls
317+
318+
$$.SANDBOX.stub(Env.prototype, 'getBoolean').returns(false); // Prevent container mode checks
319+
320+
const logStub = stubMethod($$.SANDBOX, SfCommand.prototype, 'log');
321+
322+
const login = await createNewLoginCommand([], false, undefined);
323+
await login.run();
324+
325+
// Verify that log was called with the verification code message
326+
const verificationCode = getVerificationCode(codeBuilderState);
327+
const calls = logStub.getCalls();
328+
const verificationCodeCall = calls.find(
329+
(call) => typeof call.args[0] === 'string' && call.args[0].includes(verificationCode)
330+
);
331+
expect(verificationCodeCall).to.exist;
332+
expect(verificationCode).to.match(/^[0-9a-f]{4}$/);
333+
expect(verificationCodeCall?.args[0]).to.include(messages.getMessage('verificationCode', [verificationCode]));
334+
});
335+
336+
it('should not display verification code when CODE_BUILDER_STATE env var is not set', async () => {
337+
const envStub = stubMethod($$.SANDBOX, Env.prototype, 'getString');
338+
envStub.withArgs('CODE_BUILDER_STATE').returns(undefined);
339+
envStub.returns('');
340+
341+
$$.SANDBOX.stub(Env.prototype, 'getBoolean').returns(false); // Prevent container mode checks
342+
343+
const logStub = $$.SANDBOX.stub(SfCommand.prototype, 'log');
344+
const logSuccessStub = $$.SANDBOX.stub(SfCommand.prototype, 'logSuccess');
345+
346+
const login = await createNewLoginCommand([], false, undefined);
347+
await login.run();
348+
349+
// Verify that log was NOT called for verification code
350+
expect(logStub.callCount).to.equal(0);
351+
const calls = logSuccessStub.getCalls();
352+
const verificationCodeCall = calls.find(
353+
(call) => call.args[0]?.includes('Verification Code') || call.args[0]?.includes('If prompted')
354+
);
355+
expect(verificationCodeCall).to.not.exist;
356+
expect(logSuccessStub.callCount).to.equal(1);
357+
});
305358
});

0 commit comments

Comments
 (0)