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

styra-link: correct password flow #81

Merged
merged 3 commits into from
Apr 22, 2024
Merged

styra-link: correct password flow #81

merged 3 commits into from
Apr 22, 2024

Conversation

msorens
Copy link
Collaborator

@msorens msorens commented Apr 17, 2024

What code changed, and why?

Several issues revolving around the password entry flow when installing the Styra CLI from the plugin.
DAS-770, DAS-771, DAS-772.

Definition of done

OLD:
image

NEW:
image

  1. fix poor error reporting upon bad password.

  2. allow password retries without re-downloading full binary: Add loop for retry but move the binary fetch outside the loop

  3. cancel out of password entry closes progress bar.

How to test

You can install either from source code or from GitHub.

Install from source

  1. Switch to current branch.
  2. Run npm install.
  3. Open project in VSCode.
  4. In the debugger be sure you have "Run Extension" mode selected.
  5. Invoke "run" (F5).

Install from GitHub

  1. Go to the latest release on the release page.
  2. Download the additional version piggybacked into that release, labelled vscode-styra-2.0.1-next.4.vsix.
  3. Install via the standard command: code --install-extension vscode-styra-2.0.1-next.4.vsix

Exercise the Code

Related Resources

1. fix poor error reporting upon bad password.
```
ERROR: CLI installation failed Error: Password: Sorry, try again.
Password:
sudo: no password was provided
sudo: 1 incorrect password attempt
```

2. allow password retries without re-downloading full binary
Add loop for retry but only fetch the binary on the first pass

3. cancel out of password entry closes progress bar
Move `collectInputs` out of `await IDE.withProgress`.
Duh; do not need to include the binary download in the loop at all.
Comment on lines +65 to +66
// eslint-disable-next-line no-constant-condition
while (true) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprised it is not smart enough to recognize the loop does have exits.

Comment on lines +73 to +74
if ((err as Error).message.includes('Sorry, try again')) {
info('invalid password; try again...');
Copy link
Collaborator Author

@msorens msorens Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add in a specific check for a password failure and, if found:
(a) print a clean, short message instead of the cryptic, verbose one (see image above), and
(b) do not return from the function yet, so it loops.

Comment on lines -185 to -189
const state = await this.collectInputs();
// see https://stackoverflow.com/q/39785436/115690 for ideas on running sudo
const args = ['-c', `echo ${state.pwd} | sudo -S bash -c 'mv ${tempFileLocation} ${this.ExeFile}'`];
// vital to run in quiet mode so password does not display
await new CommandRunner().runShellCmd('sh', args, {progressTitle: '', quiet: true});
Copy link
Collaborator Author

@msorens msorens Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By moving collectInputs outside of the IDE.withProgress block, the user can now abort the operation cleanly (by pressing Escape in the text input box prompting for the password). Inside the IDE.withProgress block, a progress bar appears until finished, and that progress bar did not clean up when aborting with Escape.

if (await StyraInstall.styraCmdExists()) {
if (await this.styraCmdExists()) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a mix of class name vs. this. Making them all consistent.

info('Installing Styra CLI. This may take a few minutes...');
try {
await this.installStyra();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separating installStyra into downloadBinary and installOnPath.

Comment on lines -264 to +281
shouldResume
shouldResume // TODO: override and delete temp file
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for later; low priority

Comment on lines +36 to +41
function setPrivateMock(functionName: string, mock: jest.Mock) {
(StyraInstall as any)[functionName] = mock;
}

beforeEach(() => {
// eslint-disable-next-line dot-notation
StyraInstall['installStyra'] = jest.fn().mockResolvedValue('');
setPrivateMock('downloadBinary', jest.fn().mockResolvedValue(''));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introduced setPrivateMock to get rid of the smattering of eslint disablements.

@msorens msorens marked this pull request as ready for review April 17, 2024 18:40
@msorens msorens requested a review from srenatus April 20, 2024 18:15
} else {
const state = await this.collectInputs();
// see https://stackoverflow.com/q/39785436/115690 for ideas on running sudo
const args = ['-c', `echo ${state.pwd} | sudo -S bash -c 'mv ${tempFileLocation} ${this.ExeFile}'`];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] I know this is copied code, but I still don't quite like this. I'm always getting nervous when any tool asks me to input my password. Be that as it may, I suppose we're not here to discuss this. Anyway...

This particular method seems icky, too -- multi-user machines are no longer the norm, but any other process on the machine could read the user's password from ps output if they're eager to. Can we not just open a shell with the sudo call? if the user inputs their password there it'll always be safe.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I certainly agree with your point but I am not sure there is a way to give a user a shell prompt from within a VSCode command. I like the idea though, so will put it on my backlog but merge as is for now. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only winning move is not to play -- we can install the binary anywhere, and use it from anywhere. So we can use a location where an unprivileged user can write to. .styra/bin/ or something. We'll add a note saying that they need to add that to their PATH to have it be available on the command line. If they only interact with the link tool using the VSCode plugin, there's no need for updating the $PATH even.

@msorens msorens merged commit d517cb0 into main Apr 22, 2024
4 checks passed
@msorens msorens deleted the msorens/correct-pwd-flow branch April 22, 2024 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants