-
Notifications
You must be signed in to change notification settings - Fork 11
/
access-token.ts
127 lines (115 loc) · 4.81 KB
/
access-token.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { Flags, loglevel, SfCommand } from '@salesforce/sf-plugins-core';
import { AuthFields, AuthInfo, Messages, matchesAccessToken, SfError, StateAggregator } from '@salesforce/core';
import { env } from '@salesforce/kit';
import { InferredFlags } from '@oclif/core/interfaces';
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@salesforce/plugin-auth', 'accesstoken.store');
const commonMessages = Messages.loadMessages('@salesforce/plugin-auth', 'messages');
const ACCESS_TOKEN_FORMAT = '"<org id>!<accesstoken>"';
export default class LoginAccessToken extends SfCommand<AuthFields> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');
public static readonly deprecateAliases = true;
public static readonly aliases = ['force:auth:accesstoken:store', 'auth:accesstoken:store'];
public static readonly flags = {
'instance-url': Flags.url({
char: 'r',
summary: commonMessages.getMessage('flags.instance-url.summary'),
description: commonMessages.getMessage('flags.instance-url.description'),
required: true,
deprecateAliases: true,
aliases: ['instanceurl'],
}),
'set-default-dev-hub': Flags.boolean({
char: 'd',
summary: commonMessages.getMessage('flags.set-default-dev-hub.summary'),
default: false,
deprecateAliases: true,
aliases: ['setdefaultdevhub', 'setdefaultdevhubusername'],
}),
'set-default': Flags.boolean({
char: 's',
summary: commonMessages.getMessage('flags.set-default.summary'),
default: false,
deprecateAliases: true,
aliases: ['setdefaultusername'],
}),
alias: Flags.string({
char: 'a',
summary: commonMessages.getMessage('flags.alias.summary'),
deprecateAliases: true,
aliases: ['setalias'],
}),
'no-prompt': Flags.boolean({
char: 'p',
summary: commonMessages.getMessage('flags.no-prompt.summary'),
required: false,
default: false,
deprecateAliases: true,
aliases: ['noprompt'],
}),
loglevel,
};
private flags!: InferredFlags<typeof LoginAccessToken.flags>;
public async run(): Promise<AuthFields> {
const { flags } = await this.parse(LoginAccessToken);
this.flags = flags;
const instanceUrl = flags['instance-url'].href;
const accessToken = await this.getAccessToken();
const authInfo = await this.getUserInfo(accessToken, instanceUrl);
return this.storeAuthFromAccessToken(authInfo);
}
// because stubbed on the test (instead of stubbing in core)
// eslint-disable-next-line class-methods-use-this
private async getUserInfo(accessToken: string, instanceUrl: string): Promise<AuthInfo> {
return AuthInfo.create({ accessTokenOptions: { accessToken, instanceUrl, loginUrl: instanceUrl } });
}
private async storeAuthFromAccessToken(authInfo: AuthInfo): Promise<AuthFields> {
if (await this.overwriteAuthInfo(authInfo.getUsername())) {
await this.saveAuthInfo(authInfo);
const successMsg = commonMessages.getMessage('authorizeCommandSuccess', [
authInfo.getUsername(),
authInfo.getFields(true).orgId,
]);
this.logSuccess(successMsg);
}
return authInfo.getFields(true);
}
private async saveAuthInfo(authInfo: AuthInfo): Promise<void> {
await authInfo.save();
await authInfo.handleAliasAndDefaultSettings({
alias: this.flags.alias,
setDefault: this.flags['set-default'],
setDefaultDevHub: this.flags['set-default-dev-hub'],
});
await AuthInfo.identifyPossibleScratchOrgs(authInfo.getFields(true), authInfo);
}
private async overwriteAuthInfo(username: string): Promise<boolean> {
if (!this.flags['no-prompt']) {
const stateAggregator = await StateAggregator.getInstance();
if (await stateAggregator.orgs.exists(username)) {
return this.confirm({ message: messages.getMessage('overwriteAccessTokenAuthUserFile', [username]) });
}
}
return true;
}
private async getAccessToken(): Promise<string> {
const accessToken =
env.getString('SF_ACCESS_TOKEN') ??
env.getString('SFDX_ACCESS_TOKEN') ??
(this.flags['no-prompt'] === true
? '' // will throw when validating
: await this.secretPrompt({ message: commonMessages.getMessage('accessTokenStdin') }));
if (!matchesAccessToken(accessToken)) {
throw new SfError(messages.getMessage('invalidAccessTokenFormat', [ACCESS_TOKEN_FORMAT]));
}
return accessToken;
}
}