Skip to content

Commit

Permalink
Merge pull request #18 from salesforcecli/wr/savePasswordToFile
Browse files Browse the repository at this point in the history
chore: save encrypted password to authfile
  • Loading branch information
shetzel authored Jan 22, 2021
2 parents 77f27a3 + 3cea55a commit 911c955
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 90 deletions.
2 changes: 1 addition & 1 deletion messages/create.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"description": "create a user for a scratch org",
"examples": [
"sfdx force:user:create",
"sfdx force:user:create -a testuser1 -f config/project-user-def.json",
"sfdx force:user:create -a testuser1 -f config/project-user-def.json profileName='Chatter Free User'",
"sfdx force:user:create [email protected] [email protected] permsets=DreamHouse",
"sfdx force:user:create -f config/project-user-def.json [email protected] generatepassword=true"
],
Expand Down
13 changes: 7 additions & 6 deletions src/commands/force/user/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
User,
UserFields,
} from '@salesforce/core';
import { QueryResult } from 'jsforce';
import { getString, Dictionary, isArray } from '@salesforce/ts-types';
import { flags, FlagsConfig, SfdxCommand } from '@salesforce/command';

Expand Down Expand Up @@ -126,6 +127,7 @@ export class UserCreateCommand extends SfdxCommand {
if (this.flags.setalias) {
const alias: Aliases = await Aliases.create(Aliases.getDefaultOptions());
alias.set(this.flags.setalias, fields.username);
await alias.write();
}

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

if (this.varargs) {
Object.keys(this.varargs).forEach((key) => {
if (defaultFields[key]) {
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];
}
defaultFields[this.lowerFirstLetter(key)] = this.varargs[key];
});
}

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

Expand Down
12 changes: 7 additions & 5 deletions src/commands/force/user/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
import * as os from 'os';
import { SfdxCommand } from '@salesforce/command';
import { Messages, Connection, Aliases, AuthInfo } from '@salesforce/core';
import { Messages, Connection, Aliases, AuthInfo, ConfigAggregator } from '@salesforce/core';

Messages.importMessagesDirectory(__dirname);
const messages = Messages.loadMessages('@salesforce/plugin-user', 'list');
Expand Down Expand Up @@ -38,14 +38,16 @@ export class UserListCommand extends SfdxCommand {
const userInfos: UserInfo = await this.buildUserInfos();
const profileInfos: ProfileInfo = await this.buildProfileInfos();
const userAuthData: AuthInfo[] = await this.org.readUserAuthFiles();

const alias = await Aliases.fetch(this.flags.targetusername);
const aliases = await Aliases.create(Aliases.getDefaultOptions());

const authList: AuthList[] = userAuthData.map((authData) => {
const username = authData.getUsername();

// if they passed in a alias and it maps to something we have an Alias.
const alias = aliases.getKeysByValue(authData.getUsername())[0];
const configAgg = ConfigAggregator.getInstance();
const defaultUserOrAlias = configAgg.getLocalConfig().get('defaultusername');
return {
defaultMarker: authData.getFields().scratchAdminUsername ? '' : '(A)',
defaultMarker: defaultUserOrAlias === username || defaultUserOrAlias === alias ? '(A)' : '',
alias: alias || '',
username,
profileName: profileInfos[userInfos[username].ProfileId],
Expand Down
2 changes: 2 additions & 0 deletions src/commands/force/user/password/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ export class UserPasswordGenerateCommand extends SfdxCommand {
await user.assignPassword(authInfo, password);
password.value((pass) => {
this.passwordData.push({ username: aliasOrUsername, password: pass.toString('utf-8') });
authInfo.update({ password: pass.toString('utf-8') });
});
await authInfo.save();
} catch (e) {
if (e.message.includes('Cannot set password for self')) {
throw SfdxError.create('@salesforce/plugin-user', 'password.generate', 'noSelfSetError');
Expand Down
54 changes: 50 additions & 4 deletions test/commands/user/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/* eslint-disable @typescript-eslint/ban-ts-ignore */

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

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

if (readsFile) {
stubMethod($$.SANDBOX, fs, 'readJson').resolves({ generatepassword: true });
stubMethod($$.SANDBOX, Connection.prototype, 'query').resolves({
records: [{ Id: '12345678' }],
});
stubMethod($$.SANDBOX, Logger.prototype, 'debug');
stubMethod($$.SANDBOX, fs, 'readJson').resolves(readsFile);
}
}

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

test
.do(async () => {
await prepareStubs({}, true);
await prepareStubs({}, { generatepassword: true });
})
.stdout()
.command([
Expand Down Expand Up @@ -165,6 +169,48 @@ describe('force:user:create', () => {
expect(result).to.deep.equal(expected);
});

test
.do(async () => {
await prepareStubs({}, { generatepassword: true, profileName: 'System Administrator' });
})
.stdout()
.command([
'force:user:create',
'--json',
'--definitionfile',
'parent/child/file.json',
'--targetusername',
'[email protected]',
'--targetdevhubusername',
'[email protected]',
'[email protected]',
'generatepassword=false',
"profileName='Chatter Free User'",
])
// we set generatepassword=false in the varargs, in the definitionfile we have generatepassword=true, so we SHOULD NOT generate a password
// we should override the profileName with 'Chatter Free User'
.it(
'will merge fields from the cli args, and the definitionfile correctly, preferring cli args, cli args > file > default',
(ctx) => {
const expected = {
alias: 'testAlias',
email: '[email protected]',
emailEncodingKey: 'UTF-8',
id: '0052D0000043PawWWR',
languageLocaleKey: 'en_US',
lastName: 'User',
localeSidKey: 'en_US',
orgId: 'abc123',
// note the new profileId 12345678 -> Chatter Free User from var args
profileId: '12345678',
timeZoneSidKey: 'America/Los_Angeles',
username: '[email protected]',
};
const result = JSON.parse(ctx.stdout).result;
expect(result).to.deep.equal(expected);
}
);

test
.do(async () => {
await prepareStubs({ license: true }, false);
Expand Down
69 changes: 65 additions & 4 deletions test/commands/user/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
*/

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

describe('force:user:list', () => {
async function prepareStubs() {
async function prepareStubs(defaultUser?: boolean) {
stubMethod($$.SANDBOX, Org.prototype, 'getConnection').callsFake(() => Connection.prototype);
stubMethod($$.SANDBOX, Org.prototype, 'readUserAuthFiles').returns([
{
Expand All @@ -28,7 +28,11 @@ describe('force:user:list', () => {
},
]);
stubMethod($$.SANDBOX, Org.prototype, 'getOrgId').returns('abc123');
stubMethod($$.SANDBOX, Aliases, 'fetch').resolves('testAlias');
stubMethod($$.SANDBOX, Aliases.prototype, 'getKeysByValue').returns(['testAlias']);
if (defaultUser) {
const cfa = ConfigAggregator.getInstance();
stubMethod($$.SANDBOX, cfa, 'getLocalConfig').returns({ get: () => 'testAlias' });
}
stubMethod($$.SANDBOX, Connection.prototype, 'query')
.withArgs('SELECT username, profileid, id FROM User')
.resolves({
Expand Down Expand Up @@ -60,6 +64,31 @@ describe('force:user:list', () => {
});
}

test
.do(async () => {
await prepareStubs();
})
.stdout()
.command(['force:user:list', '--json', '--targetusername', 'testUser', '--targetdevhubusername', '[email protected]'])
.it('should display the correct information from the default user', (ctx) => {
// testUser1@test.com is aliased to testUser
const expected = [
{
defaultMarker: '',
alias: 'testAlias',
username: '[email protected]',
profileName: 'Analytics Cloud Integration User',
orgId: 'abc123',
accessToken: 'accessToken',
instanceUrl: 'instanceURL',
loginUrl: 'login.test.com',
userId: '0052D0000043PbGQAU',
},
];
const result = JSON.parse(ctx.stdout).result;
expect(result).to.deep.equal(expected);
});

test
.do(async () => {
await prepareStubs();
Expand All @@ -73,7 +102,39 @@ describe('force:user:list', () => {
'--targetdevhubusername',
'[email protected]',
])
.it('should display the correct information from the default user', (ctx) => {
.it('should display the correct information from the default user with alias', (ctx) => {
// testUser1@test.com is aliased to testUser
const expected = [
{
defaultMarker: '',
alias: 'testAlias',
username: '[email protected]',
profileName: 'Analytics Cloud Integration User',
orgId: 'abc123',
accessToken: 'accessToken',
instanceUrl: 'instanceURL',
loginUrl: 'login.test.com',
userId: '0052D0000043PbGQAU',
},
];
const result = JSON.parse(ctx.stdout).result;
expect(result).to.deep.equal(expected);
});

test
.do(async () => {
await prepareStubs(true);
})
.stdout()
.command([
'force:user:list',
'--json',
'--targetusername',
'[email protected]',
'--targetdevhubusername',
'[email protected]',
])
.it('should display the correct information from the default user with alias and it default', (ctx) => {
// testUser1@test.com is aliased to testUser
const expected = [
{
Expand Down
3 changes: 3 additions & 0 deletions test/commands/user/password/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe('force:user:password:generate', () => {
];
const result = JSON.parse(ctx.stdout).result;
expect(result).to.deep.equal(expected);
expect(authInfoStub.update.callCount).to.equal(2);
});

test
Expand All @@ -77,6 +78,7 @@ describe('force:user:password:generate', () => {
const expected = [{ username: '[email protected]', password: 'abc' }];
const result = JSON.parse(ctx.stdout).result;
expect(result).to.deep.equal(expected);
expect(authInfoStub.update.callCount).to.equal(1);
});

test
Expand All @@ -89,5 +91,6 @@ describe('force:user:password:generate', () => {
expect(result.message).to.equal(messages.getMessage('noSelfSetError'));
expect(result.status).to.equal(1);
expect(result.name).to.equal('noSelfSetError');
expect(authInfoStub.update.callCount).to.equal(0);
});
});
Loading

0 comments on commit 911c955

Please sign in to comment.