Skip to content

Commit 911c955

Browse files
authored
Merge pull request #18 from salesforcecli/wr/savePasswordToFile
chore: save encrypted password to authfile
2 parents 77f27a3 + 3cea55a commit 911c955

File tree

8 files changed

+222
-90
lines changed

8 files changed

+222
-90
lines changed

messages/create.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"description": "create a user for a scratch org",
33
"examples": [
44
"sfdx force:user:create",
5-
"sfdx force:user:create -a testuser1 -f config/project-user-def.json",
5+
"sfdx force:user:create -a testuser1 -f config/project-user-def.json profileName='Chatter Free User'",
66
"sfdx force:user:create username=testuser1@my.org email=me@my.org permsets=DreamHouse",
77
"sfdx force:user:create -f config/project-user-def.json email=me@my.org generatepassword=true"
88
],

src/commands/force/user/create.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
User,
1919
UserFields,
2020
} from '@salesforce/core';
21+
import { QueryResult } from 'jsforce';
2122
import { getString, Dictionary, isArray } from '@salesforce/ts-types';
2223
import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command';
2324

@@ -126,6 +127,7 @@ export class UserCreateCommand extends SfdxCommand {
126127
if (this.flags.setalias) {
127128
const alias: Aliases = await Aliases.create(Aliases.getDefaultOptions());
128129
alias.set(this.flags.setalias, fields.username);
130+
await alias.write();
129131
}
130132

131133
this.print(fields);
@@ -167,19 +169,18 @@ export class UserCreateCommand extends SfdxCommand {
167169

168170
if (this.varargs) {
169171
Object.keys(this.varargs).forEach((key) => {
170-
if (defaultFields[key]) {
171-
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];
172-
}
172+
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];
173173
});
174174
}
175175

176176
// check if "profileName" was passed, this needs to become a profileId before calling User.create
177177
if (defaultFields['profileName']) {
178178
const name: string = defaultFields['profileName'] || 'Standard User';
179179
this.logger.debug(`Querying org for profile name [${name}]`);
180-
const profileQuery = `SELECT id FROM profile WHERE name='${name}'`;
181-
const response = await this.org.getConnection().query(profileQuery);
182-
defaultFields.profileId = getString(response, 'records[0].Id');
180+
const response: QueryResult<{ Id: string }> = await this.org
181+
.getConnection()
182+
.query(`SELECT id FROM profile WHERE name='${name}'`);
183+
defaultFields.profileId = response.records[0].Id;
183184
delete defaultFields['profileName'];
184185
}
185186

src/commands/force/user/list.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
import * as os from 'os';
88
import { SfdxCommand } from '@salesforce/command';
9-
import { Messages, Connection, Aliases, AuthInfo } from '@salesforce/core';
9+
import { Messages, Connection, Aliases, AuthInfo, ConfigAggregator } from '@salesforce/core';
1010

1111
Messages.importMessagesDirectory(__dirname);
1212
const messages = Messages.loadMessages('@salesforce/plugin-user', 'list');
@@ -38,14 +38,16 @@ export class UserListCommand extends SfdxCommand {
3838
const userInfos: UserInfo = await this.buildUserInfos();
3939
const profileInfos: ProfileInfo = await this.buildProfileInfos();
4040
const userAuthData: AuthInfo[] = await this.org.readUserAuthFiles();
41-
42-
const alias = await Aliases.fetch(this.flags.targetusername);
41+
const aliases = await Aliases.create(Aliases.getDefaultOptions());
4342

4443
const authList: AuthList[] = userAuthData.map((authData) => {
4544
const username = authData.getUsername();
46-
45+
// if they passed in a alias and it maps to something we have an Alias.
46+
const alias = aliases.getKeysByValue(authData.getUsername())[0];
47+
const configAgg = ConfigAggregator.getInstance();
48+
const defaultUserOrAlias = configAgg.getLocalConfig().get('defaultusername');
4749
return {
48-
defaultMarker: authData.getFields().scratchAdminUsername ? '' : '(A)',
50+
defaultMarker: defaultUserOrAlias === username || defaultUserOrAlias === alias ? '(A)' : '',
4951
alias: alias || '',
5052
username,
5153
profileName: profileInfos[userInfos[username].ProfileId],

src/commands/force/user/password/generate.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ export class UserPasswordGenerateCommand extends SfdxCommand {
5757
await user.assignPassword(authInfo, password);
5858
password.value((pass) => {
5959
this.passwordData.push({ username: aliasOrUsername, password: pass.toString('utf-8') });
60+
authInfo.update({ password: pass.toString('utf-8') });
6061
});
62+
await authInfo.save();
6163
} catch (e) {
6264
if (e.message.includes('Cannot set password for self')) {
6365
throw SfdxError.create('@salesforce/plugin-user', 'password.generate', 'noSelfSetError');

test/commands/user/create.test.ts

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
/* eslint-disable @typescript-eslint/ban-ts-ignore */
99

1010
import { $$, expect, test } from '@salesforce/command/lib/test';
11-
import { Aliases, Connection, DefaultUserFields, fs, Org, User } from '@salesforce/core';
11+
import { Aliases, Connection, DefaultUserFields, fs, Logger, Org, User } from '@salesforce/core';
1212
import { stubMethod } from '@salesforce/ts-sinon';
1313
import { IConfig } from '@oclif/config';
1414
import UserCreateCommand from '../../../src/commands/force/user/create';
@@ -61,7 +61,7 @@ describe('force:user:create', () => {
6161
});
6262
});
6363

64-
async function prepareStubs(throws: { license?: boolean; duplicate?: boolean } = {}, readsFile = false) {
64+
async function prepareStubs(throws: { license?: boolean; duplicate?: boolean } = {}, readsFile?) {
6565
stubMethod($$.SANDBOX, Org.prototype, 'getConnection').callsFake(() => Connection.prototype);
6666
stubMethod($$.SANDBOX, DefaultUserFields, 'create').resolves({
6767
getFields: () => {
@@ -94,7 +94,11 @@ describe('force:user:create', () => {
9494
}
9595

9696
if (readsFile) {
97-
stubMethod($$.SANDBOX, fs, 'readJson').resolves({ generatepassword: true });
97+
stubMethod($$.SANDBOX, Connection.prototype, 'query').resolves({
98+
records: [{ Id: '12345678' }],
99+
});
100+
stubMethod($$.SANDBOX, Logger.prototype, 'debug');
101+
stubMethod($$.SANDBOX, fs, 'readJson').resolves(readsFile);
98102
}
99103
}
100104

@@ -131,7 +135,7 @@ describe('force:user:create', () => {
131135

132136
test
133137
.do(async () => {
134-
await prepareStubs({}, true);
138+
await prepareStubs({}, { generatepassword: true });
135139
})
136140
.stdout()
137141
.command([
@@ -165,6 +169,48 @@ describe('force:user:create', () => {
165169
expect(result).to.deep.equal(expected);
166170
});
167171

172+
test
173+
.do(async () => {
174+
await prepareStubs({}, { generatepassword: true, profileName: 'System Administrator' });
175+
})
176+
.stdout()
177+
.command([
178+
'force:user:create',
179+
'--json',
180+
'--definitionfile',
181+
'parent/child/file.json',
182+
'--targetusername',
183+
'testUser1@test.com',
184+
'--targetdevhubusername',
185+
'devhub@test.com',
186+
'email=me@my.org',
187+
'generatepassword=false',
188+
"profileName='Chatter Free User'",
189+
])
190+
// we set generatepassword=false in the varargs, in the definitionfile we have generatepassword=true, so we SHOULD NOT generate a password
191+
// we should override the profileName with 'Chatter Free User'
192+
.it(
193+
'will merge fields from the cli args, and the definitionfile correctly, preferring cli args, cli args > file > default',
194+
(ctx) => {
195+
const expected = {
196+
alias: 'testAlias',
197+
email: 'me@my.org',
198+
emailEncodingKey: 'UTF-8',
199+
id: '0052D0000043PawWWR',
200+
languageLocaleKey: 'en_US',
201+
lastName: 'User',
202+
localeSidKey: 'en_US',
203+
orgId: 'abc123',
204+
// note the new profileId 12345678 -> Chatter Free User from var args
205+
profileId: '12345678',
206+
timeZoneSidKey: 'America/Los_Angeles',
207+
username: '1605130295132_test-j6asqt5qoprs@example.com',
208+
};
209+
const result = JSON.parse(ctx.stdout).result;
210+
expect(result).to.deep.equal(expected);
211+
}
212+
);
213+
168214
test
169215
.do(async () => {
170216
await prepareStubs({ license: true }, false);

test/commands/user/list.test.ts

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
*/
77

88
import { $$, expect, test } from '@salesforce/command/lib/test';
9-
import { Aliases, Connection, Org } from '@salesforce/core';
9+
import { Aliases, ConfigAggregator, Connection, Org } from '@salesforce/core';
1010
import { stubMethod } from '@salesforce/ts-sinon';
1111

1212
describe('force:user:list', () => {
13-
async function prepareStubs() {
13+
async function prepareStubs(defaultUser?: boolean) {
1414
stubMethod($$.SANDBOX, Org.prototype, 'getConnection').callsFake(() => Connection.prototype);
1515
stubMethod($$.SANDBOX, Org.prototype, 'readUserAuthFiles').returns([
1616
{
@@ -28,7 +28,11 @@ describe('force:user:list', () => {
2828
},
2929
]);
3030
stubMethod($$.SANDBOX, Org.prototype, 'getOrgId').returns('abc123');
31-
stubMethod($$.SANDBOX, Aliases, 'fetch').resolves('testAlias');
31+
stubMethod($$.SANDBOX, Aliases.prototype, 'getKeysByValue').returns(['testAlias']);
32+
if (defaultUser) {
33+
const cfa = ConfigAggregator.getInstance();
34+
stubMethod($$.SANDBOX, cfa, 'getLocalConfig').returns({ get: () => 'testAlias' });
35+
}
3236
stubMethod($$.SANDBOX, Connection.prototype, 'query')
3337
.withArgs('SELECT username, profileid, id FROM User')
3438
.resolves({
@@ -60,6 +64,31 @@ describe('force:user:list', () => {
6064
});
6165
}
6266

67+
test
68+
.do(async () => {
69+
await prepareStubs();
70+
})
71+
.stdout()
72+
.command(['force:user:list', '--json', '--targetusername', 'testUser', '--targetdevhubusername', 'devhub@test.com'])
73+
.it('should display the correct information from the default user', (ctx) => {
74+
// testUser1@test.com is aliased to testUser
75+
const expected = [
76+
{
77+
defaultMarker: '',
78+
alias: 'testAlias',
79+
username: 'testuser@test.com',
80+
profileName: 'Analytics Cloud Integration User',
81+
orgId: 'abc123',
82+
accessToken: 'accessToken',
83+
instanceUrl: 'instanceURL',
84+
loginUrl: 'login.test.com',
85+
userId: '0052D0000043PbGQAU',
86+
},
87+
];
88+
const result = JSON.parse(ctx.stdout).result;
89+
expect(result).to.deep.equal(expected);
90+
});
91+
6392
test
6493
.do(async () => {
6594
await prepareStubs();
@@ -73,7 +102,39 @@ describe('force:user:list', () => {
73102
'--targetdevhubusername',
74103
'devhub@test.com',
75104
])
76-
.it('should display the correct information from the default user', (ctx) => {
105+
.it('should display the correct information from the default user with alias', (ctx) => {
106+
// testUser1@test.com is aliased to testUser
107+
const expected = [
108+
{
109+
defaultMarker: '',
110+
alias: 'testAlias',
111+
username: 'testuser@test.com',
112+
profileName: 'Analytics Cloud Integration User',
113+
orgId: 'abc123',
114+
accessToken: 'accessToken',
115+
instanceUrl: 'instanceURL',
116+
loginUrl: 'login.test.com',
117+
userId: '0052D0000043PbGQAU',
118+
},
119+
];
120+
const result = JSON.parse(ctx.stdout).result;
121+
expect(result).to.deep.equal(expected);
122+
});
123+
124+
test
125+
.do(async () => {
126+
await prepareStubs(true);
127+
})
128+
.stdout()
129+
.command([
130+
'force:user:list',
131+
'--json',
132+
'--targetusername',
133+
'testUser1@test.com',
134+
'--targetdevhubusername',
135+
'devhub@test.com',
136+
])
137+
.it('should display the correct information from the default user with alias and it default', (ctx) => {
77138
// testUser1@test.com is aliased to testUser
78139
const expected = [
79140
{

test/commands/user/password/generate.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ describe('force:user:password:generate', () => {
6767
];
6868
const result = JSON.parse(ctx.stdout).result;
6969
expect(result).to.deep.equal(expected);
70+
expect(authInfoStub.update.callCount).to.equal(2);
7071
});
7172

7273
test
@@ -77,6 +78,7 @@ describe('force:user:password:generate', () => {
7778
const expected = [{ username: 'defaultusername@test.com', password: 'abc' }];
7879
const result = JSON.parse(ctx.stdout).result;
7980
expect(result).to.deep.equal(expected);
81+
expect(authInfoStub.update.callCount).to.equal(1);
8082
});
8183

8284
test
@@ -89,5 +91,6 @@ describe('force:user:password:generate', () => {
8991
expect(result.message).to.equal(messages.getMessage('noSelfSetError'));
9092
expect(result.status).to.equal(1);
9193
expect(result.name).to.equal('noSelfSetError');
94+
expect(authInfoStub.update.callCount).to.equal(0);
9295
});
9396
});

0 commit comments

Comments
 (0)