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

feat: adds keyring credentials provider for accounts #1483

Merged
merged 12 commits into from
May 6, 2024
Merged

Conversation

tdstein
Copy link
Collaborator

@tdstein tdstein commented Apr 30, 2024

Intent

Adds support for adding credentials via the VSCode credentials pane.

Type of Change

    • Bug Fix
    • New Feature
    • Breaking Change
    • Documentation
    • Refactor
    • Tooling

Approach

A new API endpoint (POST /credentials) accepts an API Key credential. No other authentication types are supported at this time. This endpoint uses the go-keyring library to write to the OS specific credentials store. This is the "Keychain Access" application on macOS.

A '+' button is added to the credentials pane, which triggers a multi-step form accepting a name, URL, and API Key. This then POST to the aforementioned endpoint.

A new "Account Provider" is added on the backend, which reads the credentials and then maps them to the existing "Account" structure.

Automated Tests

I added a few backend tests.

Directions for Reviewers

Try it out. I was able to deploy successfully using an API key on the keyring.

We should test on Windows and LInux to verify that the go-keyring library works as advertised.

Checklist

Comment on lines +84 to +86
r.Handle(ToPath("credentials"), GetCredentialsHandlerFunc(log)).
Methods(http.MethodGet)

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'll probably delete this. But, you can call it to see the list of credentials on the keyring.

@tdstein tdstein force-pushed the tdstein/credentials branch from 9e3e268 to 3e534f3 Compare April 30, 2024 20:53
Copy link
Contributor

@mmarchetti mmarchetti left a comment

Choose a reason for hiding this comment

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

This is great!

@tdstein tdstein force-pushed the tdstein/credentials branch 4 times, most recently from 9a9a54a to bf2d11f Compare May 1, 2024 19:03
@tdstein
Copy link
Collaborator Author

tdstein commented May 1, 2024

@kgartland-rstudio - I would like to get this tested on Windows before I merge. I need to verify that go-keyring works as expected. Adding a credential using the VSCode UI will exercise the necessary codepaths.

@tdstein tdstein force-pushed the tdstein/credentials branch 3 times, most recently from 21d328d to 3ed4c94 Compare May 1, 2024 19:49
@tdstein tdstein requested a review from mmarchetti May 1, 2024 19:58
Copy link
Collaborator

@dotNomad dotNomad left a comment

Choose a reason for hiding this comment

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

This worked great for me. Would like a deletion, but that can be a follow-up.

Did notice some minor typing mistakes, and called out using our multi-step input pattern.

apiKey: string;
};

export type Credentials = Map<string, Credential>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like this isn't used.

// 200 - success
// 400 - bad request
// 500 - internal server error
createOrUpdate(cred: Credential) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: a lot of our other resources take parameters rather than a single object. I think a single object is totally fine here since they are all required, and past 3 parameters its much clearer to use an object. Just something I noticed

@@ -83,28 +83,142 @@ export class CredentialsTreeDataProvider
isEmpty ? "empty" : "notEmpty",
);
}

public add = async () => {
const name = await getServerNameFromInputBox();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Calling each of these in succession is effectively a multi step input. We have several multiStepInputs that also have the validate function examples rather than using notifications.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this works I'd be fine with both of these (multistep input, and validation) being follow-ups

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds good. I wasn't sure if it was needed at the outset, but now that this is complete, it makes sense to use the abstraction.

export class CredentialsTreeItem extends TreeItem {
contextValue = "posit.publisher.credentials.tree.item";

constructor(account: Account) {
super(account.name);
this.tooltip = this.getTooltip(account);
this.iconPath = new ThemeIcon("key");
this.description = `${account.url}`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

@tdstein tdstein force-pushed the tdstein/credentials branch 2 times, most recently from a63b8e2 to 9e29e6e Compare May 2, 2024 19:26
Copy link
Collaborator

@dotNomad dotNomad left a comment

Choose a reason for hiding this comment

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

This is fantastic. Thanks for those changes the new validation is awesome. Only caught one area where we should catch errors.

input = input.trim();
if (input.trim() === "") {
return {
message: "Oops! It seems like your forgot something.",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Honestly I really like playful messages like this in software.

@tdstein tdstein force-pushed the tdstein/credentials branch from a966593 to 3160925 Compare May 5, 2024 12:51
@tdstein tdstein merged commit 1186004 into main May 6, 2024
16 checks passed
@tdstein tdstein deleted the tdstein/credentials branch May 6, 2024 15:55
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.

3 participants