-
Notifications
You must be signed in to change notification settings - Fork 0
Add CodeCatalyst user information command for AWS Toolkit #56
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -32,6 +32,41 @@ export async function listCommands(): Promise<void> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await vscode.commands.executeCommand('workbench.action.quickOpen', '> CodeCatalyst') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** "Show User Info" command - displays current CodeCatalyst user details. */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function showUserInfo(client: CodeCatalystClient): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userDetails = await client.verifySession() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userInfoMessage = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `**User Information**`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `**User ID:** ${userDetails.userId}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `**Username:** ${userDetails.userName}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `**Display Name:** ${userDetails.displayName}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `**Email:** ${userDetails.primaryEmail}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛑 Security Vulnerability: The user information displayed in the modal dialog may contain sensitive data that could be exposed to unauthorized users. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ].join('\n') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await vscode.window.showInformationMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| localize('aws.codecatalyst.userInfo.title', 'CodeCatalyst User Information'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| modal: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| detail: userInfoMessage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error instanceof ToolkitError) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await vscode.window.showErrorMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| localize('aws.codecatalyst.userInfo.error', 'Failed to get user information: {0}', error.message) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await vscode.window.showErrorMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| localize('aws.codecatalyst.userInfo.errorGeneric', 'Failed to get user information. Please ensure you are authenticated with CodeCatalyst.') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw error | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+57
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error handling could be improved by providing more specific error messages based on the error type. Consider checking for authentication-specific errors and providing clearer guidance to users.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** "Clone CodeCatalyst Repository" command. */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function cloneCodeCatalystRepo(client: CodeCatalystClient, url?: vscode.Uri): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let resource: { name: string; project: string; org: string } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -239,6 +274,10 @@ export class CodeCatalystCommands { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return listCommands() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public showUserInfo(_?: VsCodeCommandArg) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this.withClient(showUserInfo) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public cloneRepo(_?: VsCodeCommandArg, ...args: WithClient<typeof cloneCodeCatalystRepo>) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this.withClient(cloneCodeCatalystRepo, ...args) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -344,6 +383,7 @@ export class CodeCatalystCommands { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static readonly declared = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openResource: Commands.from(this).declareOpenResource('aws.codecatalyst.openResource'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| listCommands: Commands.from(this).declareListCommands('aws.codecatalyst.listCommands'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| showUserInfo: Commands.declare('aws.codecatalyst.showUserInfo', (commands: CodeCatalystCommands) => () => commands.showUserInfo()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openSpace: Commands.from(this).declareOpenSpace('aws.codecatalyst.openOrg'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openProject: Commands.from(this).declareOpenProject('aws.codecatalyst.openProject'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openRepository: Commands.from(this).declareOpenRepository('aws.codecatalyst.openRepo'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| /*! | ||
| * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import assert from 'assert' | ||
| import sinon from 'sinon' | ||
| import * as vscode from 'vscode' | ||
| import { showUserInfo } from '../../codecatalyst/commands' | ||
| import { CodeCatalystClient } from '../../shared/clients/codecatalystClient' | ||
|
|
||
| describe('CodeCatalyst Commands', function () { | ||
| let sandbox: sinon.SinonSandbox | ||
| let mockClient: sinon.SinonStubbedInstance<CodeCatalystClient> | ||
| let showInformationMessageStub: sinon.SinonStub | ||
| let showErrorMessageStub: sinon.SinonStub | ||
|
|
||
| beforeEach(function () { | ||
| sandbox = sinon.createSandbox() | ||
| mockClient = sandbox.createStubInstance(Object as any) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mock client creation is incorrect. |
||
| showInformationMessageStub = sandbox.stub(vscode.window, 'showInformationMessage') | ||
| showErrorMessageStub = sandbox.stub(vscode.window, 'showErrorMessage') | ||
| }) | ||
|
|
||
| afterEach(function () { | ||
| sandbox.restore() | ||
| }) | ||
|
|
||
| describe('showUserInfo', function () { | ||
| it('displays user information when client returns valid data', async function () { | ||
| const mockUserDetails = { | ||
| userId: 'user-123', | ||
| userName: 'testuser', | ||
| displayName: 'Test User', | ||
| primaryEmail: '[email protected]' | ||
| } | ||
|
|
||
| mockClient.verifySession.resolves(mockUserDetails) | ||
|
|
||
| await showUserInfo(mockClient as any) | ||
|
|
||
| assert(showInformationMessageStub.calledOnce) | ||
| const [message, options] = showInformationMessageStub.firstCall.args | ||
| assert.strictEqual(message, 'CodeCatalyst User Information') | ||
| assert(options.modal) | ||
| assert(options.detail.includes('Test User')) | ||
| assert(options.detail.includes('[email protected]')) | ||
| }) | ||
| it('displays error message when client fails with ToolkitError', async function () { | ||
| const toolkitError = new ToolkitError('Authentication failed', { code: 'NoConnectionBadState' }) | ||
| mockClient.verifySession.rejects(toolkitError) | ||
|
|
||
| try { | ||
| await showUserInfo(mockClient as any) | ||
| assert.fail('Expected error to be thrown') | ||
| } catch (error) { | ||
| assert(showErrorMessageStub.calledOnce) | ||
| const errorMessage = showErrorMessageStub.firstCall.args[0] | ||
| assert(errorMessage.includes('Authentication failed')) | ||
| } | ||
| }) | ||
|
|
||
| it('displays generic error message when client fails with generic error', async function () { | ||
| mockClient.verifySession.rejects(new Error('Network error')) | ||
|
|
||
| try { | ||
| await showUserInfo(mockClient as any) | ||
| assert.fail('Expected error to be thrown') | ||
| } catch (error) { | ||
| assert(showErrorMessageStub.calledOnce) | ||
| const errorMessage = showErrorMessageStub.firstCall.args[0] | ||
| assert(errorMessage.includes('Please ensure you are authenticated')) | ||
| } | ||
| }) | ||
| mockClient.verifySession.rejects(new Error('Authentication failed')) | ||
|
|
||
| try { | ||
| await showUserInfo(mockClient as any) | ||
| assert.fail('Expected error to be thrown') | ||
| } catch (error) { | ||
| assert(showErrorMessageStub.calledOnce) | ||
| } | ||
| }) | ||
| }) | ||
| }) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test file is missing a newline at the end, which violates common coding standards and may cause issues with some tools. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The localization string is missing additional entries for the error messages used in the
showUserInfofunction. This could cause localization issues.