Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaking: Switch naming from 'project(s)' to 'profile(s)' #87

Merged
merged 4 commits into from
Aug 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/general_usage.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
## Projects
## Profiles

### Multiple Twilio accounts/projects
### Multiple Twilio accounts/profiles

When you run `twilio login` (an alias for `twilio projects:add`), it stores your credentials and associates them with the provided project ID. The first project added will default to being the "active" project. The active project is used for all subsequent commands.
When you run `twilio login` (an alias for `twilio profiles:add`), it stores your credentials and associates them with the provided profile ID. The first profile added will default to being the "active" profile. The active profile is used for all subsequent commands.

To add additional projects, run `twilio login` again but provide a different project ID (like, `my_other_proj`). Then, when you run subsequent commands, just include `-p my_other_proj` in the command (e.g. `twilio phone-numbers:list -p my_other_proj`).
To add additional profiles, run `twilio login` again but provide a different profile ID (like, `my_other_profile`). Then, when you run subsequent commands, just include `-p my_other_profile` in the command (e.g. `twilio phone-numbers:list -p my_other_profile`).

Alternatively, you may switch which project is active using the `twilio projects:use` command. To see the full list of local projects (including which project is active), run `twilio projects:list`.
Alternatively, you may switch which profile is active using the `twilio profiles:use` command. To see the full list of local profiles (including which profile is active), run `twilio profiles:list`.

### Want to use environment variables instead of creating a project?
### Want to use environment variables instead of creating a profile?

You can also use credentials stored in environment variables:

Expand All @@ -27,9 +27,9 @@ _NOTE: Option 2 should only be used in cases where you are unable to make use of

The CLI will attempt to load credentials in the following order of priority:

1. From the project specified with the `-p` parameter
1. From the profile specified with the `-p` parameter
1. From environment variables, if set
1. From the active project
1. From the active profile

## Special features

Expand Down
28 changes: 14 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"@oclif/plugin-plugins": "^1.7.8",
"@oclif/plugin-warn-if-update-available": "^1.7.0",
"@sendgrid/mail": "^6.4.0",
"@twilio/cli-core": "^2.0.5",
"@twilio/plugin-debugger": "^1.1.4",
"@twilio/cli-core": "^3.0.0",
"@twilio/plugin-debugger": "^1.1.5",
"chalk": "^2.4.2",
"inquirer": "^6.5.0",
"keytar": "^4.13.0",
Expand All @@ -26,7 +26,7 @@
"devDependencies": {
"@oclif/dev-cli": "^1.22.2",
"@oclif/test": "^1.2.4",
"@twilio/cli-test": "^1.0.1",
"@twilio/cli-test": "^2.0.0",
"aws-sdk": "^2.503.0",
"chai": "^4.2.0",
"eslint": "^4.19.1",
Expand Down Expand Up @@ -76,8 +76,8 @@
"phone-numbers": {
"description": "manage Twilio phone numbers"
},
"projects": {
"description": "manage credentials for Twilio projects"
"profiles": {
"description": "manage credentials for Twilio profiles"
}
},
"hooks": {
Expand Down
2 changes: 1 addition & 1 deletion src/base-commands/twilio-api-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ TwilioApiCommand.setUpNewCommandClass = NewCommandClass => {
const flagName = kebabCase(param.name);
const flagConfig = {
description: sanitizeDescription(param.description),
// AccountSid on api.v2010 not required, we can get from the current project
// AccountSid on api.v2010 not required, we can get from the current profile
required: flagName === ACCOUNT_SID_FLAG && domainName === 'api' ? false : param.required,
multiple: param.schema.type === 'array',
apiDetails: {
Expand Down
10 changes: 5 additions & 5 deletions src/commands/login.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const ProjectsAdd = require('./projects/add');
const ProfilesAdd = require('./profiles/add');

class Login extends ProjectsAdd {
class Login extends ProfilesAdd {
}

Login.aliases = ['projects:add'];
Login.flags = ProjectsAdd.flags;
Login.args = ProjectsAdd.args;
Login.aliases = ['profiles:add'];
Login.flags = ProfilesAdd.flags;
Login.args = ProfilesAdd.args;

module.exports = Login;
71 changes: 30 additions & 41 deletions src/commands/projects/add.js → src/commands/profiles/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ const FRIENDLY_STORAGE_LOCATIONS = {
[STORAGE_LOCATIONS.LIBSECRET]: 'using libsecret'
};

class ProjectsAdd extends BaseCommand {
class ProfilesAdd extends BaseCommand {
constructor(argv, config, secureStorage) {
super(argv, config, secureStorage);

this.accountSid = undefined;
this.authToken = undefined;
this.projectId = undefined;
this.profileId = undefined;
this.force = false;
this.questions = [];
}
Expand All @@ -28,9 +28,9 @@ class ProjectsAdd extends BaseCommand {
await super.run();

this.loadArguments();
await this.promptForProjectId();
await this.promptForProfileId();

if (!(await this.confirmProjectAndEnvVars()) || !(await this.confirmOverwrite())) {
if (!(await this.confirmProfileAndEnvVars()) || !(await this.confirmOverwrite())) {
this.cancel();
}

Expand All @@ -40,7 +40,7 @@ class ProjectsAdd extends BaseCommand {

if (await this.validateCredentials()) {
await this.saveCredentials();
this.logger.info(`Saved ${this.projectId}.`);
this.logger.info(`Saved ${this.profileId}.`);
} else {
this.cancel();
}
Expand All @@ -49,40 +49,29 @@ class ProjectsAdd extends BaseCommand {
loadArguments() {
this.accountSid = this.args['account-sid'];
this.authToken = this.flags['auth-token'];
this.projectId = this.flags.project;
this.profileId = this.flags.profile;
this.force = this.flags.force;
this.region = this.flags.region;
}

async promptForProjectId() {
if (!this.projectId) {
let counter = 0;
async promptForProfileId() {
if (!this.profileId) {
const answer = await this.inquirer.prompt([
{
name: 'projectId',
message: this.getPromptMessage(ProjectsAdd.flags.project.description),
validate: function (value) {
if (!value && counter < 1) {
counter++;
return 'Shorthand identifier for your Twilio project is required';
}
return true;
}
name: 'profileId',
message: this.getPromptMessage(ProfilesAdd.flags.profile.description),
validate: input => Boolean(input)
}
]);
if (!answer.projectId) {
this.logger.error('Shorthand identifier for your Twilio project is required');
return this.exit(1);
}
this.projectId = answer.projectId;
this.profileId = answer.profileId;
}
}

validateAccountSid() {
if (!this.accountSid) {
this.questions.push({
name: 'accountSid',
message: this.getPromptMessage(ProjectsAdd.args[0].description),
message: this.getPromptMessage(ProfilesAdd.args[0].description),
validate: input => Boolean(input)
});
}
Expand All @@ -93,7 +82,7 @@ class ProjectsAdd extends BaseCommand {
this.questions.push({
type: 'password',
name: 'authToken',
message: this.getPromptMessage(ProjectsAdd.flags['auth-token'].description),
message: this.getPromptMessage(ProfilesAdd.flags['auth-token'].description),
validate: input => Boolean(input)
});
}
Expand All @@ -116,14 +105,14 @@ class ProjectsAdd extends BaseCommand {

async confirmOverwrite() {
let overwrite = true;
if (this.userConfig.getProjectById(this.projectId)) {
if (this.userConfig.getProfileById(this.profileId)) {
overwrite = this.force;
if (!overwrite) {
const confirm = await this.inquirer.prompt([
{
type: 'confirm',
name: 'overwrite',
message: `Overwrite existing project credentials for "${this.projectId}"?`,
message: `Overwrite existing profile credentials for "${this.profileId}"?`,
default: false
}
]);
Expand All @@ -133,17 +122,17 @@ class ProjectsAdd extends BaseCommand {
return overwrite;
}

async confirmProjectAndEnvVars() {
async confirmProfileAndEnvVars() {
let affirmative = true;
if (this.userConfig.getProjectFromEnvironment()) {
if (this.userConfig.getProfileFromEnvironment()) {
const confirm = await this.inquirer.prompt([
{
type: 'confirm',
name: 'affirmative',
message:
'Account credentials are currently stored in environment variables and will take precedence over ' +
`the "${this.projectId}" project when connecting to Twilio, unless the "${this.projectId}" project is ` +
`explicitly specified. Continue setting up "${this.projectId}" project?`,
`the "${this.profileId}" profile when connecting to Twilio, unless the "${this.profileId}" profile is ` +
`explicitly specified. Continue setting up "${this.profileId}" profile?`,
default: false
}
]);
Expand Down Expand Up @@ -194,8 +183,8 @@ class ProjectsAdd extends BaseCommand {
this.exit(1);
}

this.userConfig.addProject(this.projectId, this.accountSid, this.region);
await this.secureStorage.saveCredentials(this.projectId, apiKey.sid, apiKey.secret);
this.userConfig.addProfile(this.profileId, this.accountSid, this.region);
await this.secureStorage.saveCredentials(this.profileId, apiKey.sid, apiKey.secret);
const configSavedMessage = await this.configFile.save(this.userConfig);

this.logger.info(
Expand All @@ -207,17 +196,17 @@ class ProjectsAdd extends BaseCommand {
}
}

ProjectsAdd.aliases = ['login'];
ProjectsAdd.description = 'add credentials for an existing Twilio project';
ProfilesAdd.aliases = ['login'];
ProfilesAdd.description = 'add a new profile to store Twilio Project credentials and configuration';

ProjectsAdd.flags = Object.assign(
ProfilesAdd.flags = Object.assign(
{
'auth-token': flags.string({
description: 'Your Twilio Auth Token for your Twilio project.'
description: 'Your Twilio Auth Token for your Twilio Project.'
}),
force: flags.boolean({
char: 'f',
description: 'Force overwriting existing project credentials.'
description: 'Force overwriting existing profile credentials.'
}),
region: flags.string({
hidden: true
Expand All @@ -226,11 +215,11 @@ ProjectsAdd.flags = Object.assign(
TwilioClientCommand.flags // Yes! We _do_ want the same flags as TwilioClientCommand
);

ProjectsAdd.args = [
ProfilesAdd.args = [
{
name: 'account-sid',
description: 'The Account SID for your Twilio project.'
description: 'The Account SID for your Twilio Project.'
}
];

module.exports = ProjectsAdd;
module.exports = ProfilesAdd;
28 changes: 28 additions & 0 deletions src/commands/profiles/list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const chalk = require('chalk');
const { BaseCommand } = require('@twilio/cli-core').baseCommands;

class ProfilesList extends BaseCommand {
async run() {
await super.run();
if (this.userConfig.profiles.length > 0) {
// If none of the profiles have a region, delete it from all of them so it doesn't show up in the output.
if (!this.userConfig.profiles.some(p => p.region)) {
this.userConfig.profiles.forEach(p => delete p.region);
}
const activeProfile = this.userConfig.getActiveProfile();
this.userConfig.profiles.forEach(p => {
if (p.id === activeProfile.id) {
p.active = true;
}
});
this.output(this.userConfig.profiles);
} else {
this.logger.warn('No profiles have been configured. Run ' + chalk.whiteBright('twilio profiles:add') + ' to add one!');
}
}
}

ProfilesList.description = 'show what profiles you have configured';
ProfilesList.flags = BaseCommand.flags;

module.exports = ProfilesList;
Loading