Skip to content

Commit

Permalink
Show inline action when using password (#2178)
Browse files Browse the repository at this point in the history
* Show inline action when using password

* Fix lint
  • Loading branch information
JasonYeMSFT authored Sep 21, 2023
1 parent 266299d commit a46e202
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 10 deletions.
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@
"category": "PostgreSQL",
"command": "postgreSQL.openStoredProcedure",
"title": "Open Stored Procedure"
},
{
"category": "PostgreSQL",
"command": "postgreSQL.showPasswordlessWiki",
"title": "Learn more about authenticating with Azure Active Directory",
"icon": "$(warning)"
}
],
"submenus": [
Expand Down Expand Up @@ -604,6 +610,11 @@
"when": "view =~ /azure(ResourceGroups|Workspace|FocusView)/ && viewItem == cosmosDBGraphDatabase",
"group": "1@1"
},
{
"command": "postgreSQL.showPasswordlessWiki",
"when": "view =~ /azure(ResourceGroups|azureFocusView)/ && viewItem =~ /postgresDatabase(?![a-z])/i && viewItem =~ /usesPassword/i",
"group": "inline"
},
{
"command": "postgreSQL.createDatabase",
"when": "view =~ /(azureResourceGroups|azureFocusView)/ && viewItem =~ /postgresServer(?![a-z])/i",
Expand Down Expand Up @@ -1027,6 +1038,7 @@
"clean": "git clean -dfx",
"compile": "tsc -watch",
"package": "vsce package --githubBranch main",
"package-local": "vsce package",
"lint": "eslint --ext .ts .",
"lint-fix": "eslint --ext .ts . --fix",
"pretest": "npm run webpack-prod",
Expand Down
3 changes: 2 additions & 1 deletion src/postgres/commands/checkAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export async function checkAuthentication(context: IActionContext, treeItem: Pos
continue;
}
try {
clientConfig = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName);
const getClientConfigResult = await PostgresClientConfigFactory.getClientConfigFromNode(treeItem.parent, treeItem.databaseName);
clientConfig = getClientConfigResult.clientConfig;
} catch (error) {
const parsedError: IParsedError = parseError(error);

Expand Down
7 changes: 7 additions & 0 deletions src/postgres/commands/registerPostgresCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { defaults } from "pg";
import { languages } from "vscode";
import { connectedPostgresKey, doubleClickDebounceDelay, postgresDefaultDatabase, postgresLanguageId } from "../../constants";
import { ext } from "../../extensionVariables";
import { openUrl } from "../../utils/openUrl";
import { PostgresCodeLensProvider } from "../services/PostgresCodeLensProvider";
import { PostgresDatabaseTreeItem } from "../tree/PostgresDatabaseTreeItem";
import { configurePostgresFirewall } from "./configurePostgresFirewall";
Expand Down Expand Up @@ -50,6 +51,7 @@ export function registerPostgresCommands(): void {
registerCommandWithTreeNodeUnwrapping('postgreSQL.createStoredProcedureQuery', createPostgresStoredProcedureQuery);
registerCommandWithTreeNodeUnwrapping('postgreSQL.executeQuery', executePostgresQueryInDocument);
registerCommandWithTreeNodeUnwrapping('postgreSQL.copyConnectionString', copyConnectionString);
registerCommandWithTreeNodeUnwrapping('postgreSQL.showPasswordlessWiki', showPasswordlessWiki);
}

export async function loadPersistedPostgresDatabase(): Promise<void> {
Expand All @@ -74,3 +76,8 @@ export async function loadPersistedPostgresDatabase(): Promise<void> {
}
});
}

export async function showPasswordlessWiki(): Promise<void> {
// @todo: Create forward link
await openUrl("https://aka.ms/postgresql-passwordless-wiki");
}
10 changes: 8 additions & 2 deletions src/postgres/tree/ClientConfigFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export const postgresResourceType = "https://ossrdbms-aad.database.windows.net/"
* Creates an object that can be used to execute a postgres query with connection test and telemetry.
*/
export class PostgresClientConfigFactory {
public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<ClientConfig> {
public static async getClientConfigFromNode(treeItem: PostgresServerTreeItem, databaseName: string): Promise<{
type: "azureAd" | "password" | "connectionString",
clientConfig: ClientConfig
}> {
const parsedConnectionString = await treeItem.getFullConnectionString();
const azureUserSession = await getAzureAdUserSession();

Expand Down Expand Up @@ -54,7 +57,10 @@ export class PostgresClientConfigFactory {
context.telemetry.properties.clientConfigType = clientConfigType;
await testClientConfig(clientConfig);
});
return clientConfig;
return {
type: clientConfigType,
clientConfig
};
} catch (error) {
// If the client config failed during test, skip and try the next available one.
}
Expand Down
23 changes: 18 additions & 5 deletions src/postgres/tree/PostgresDatabaseTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/

// eslint-disable-next-line import/no-internal-modules
import { AzExtParentTreeItem, AzExtTreeItem, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
import { ClientConfig } from 'pg';
import { AzExtParentTreeItem, AzExtTreeItem, createContextValue, GenericTreeItem, IActionContext, IParsedError, parseError, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
import { ThemeIcon } from 'vscode';
import { ext } from '../../extensionVariables';
import { localize } from '../../utils/localize';
Expand All @@ -19,15 +18,17 @@ import { PostgresTablesTreeItem } from './PostgresTablesTreeItem';

export class PostgresDatabaseTreeItem extends AzExtParentTreeItem {
public static contextValue: string = "postgresDatabase";
public readonly contextValue: string = PostgresDatabaseTreeItem.contextValue;
public contextValue: string = PostgresDatabaseTreeItem.contextValue;
public readonly childTypeLabel: string = "Resource Type";
public readonly databaseName: string;
public readonly parent: PostgresServerTreeItem;
public autoSelectInTreeItemPicker: boolean = true;
public isShowingPasswordWarning: boolean;

constructor(parent: PostgresServerTreeItem, databaseName: string) {
super(parent);
this.databaseName = databaseName;
this.isShowingPasswordWarning = false;
}

public get label(): string {
Expand Down Expand Up @@ -63,7 +64,10 @@ export class PostgresDatabaseTreeItem extends AzExtParentTreeItem {
}

try {
const clientConfig: ClientConfig = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName);
const { type, clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName);
if (type === "password") {
void this.showPasswordWarning(context);
}
const children: AzExtTreeItem[] = [
new PostgresFunctionsTreeItem(this, clientConfig),
new PostgresTablesTreeItem(this, clientConfig)
Expand Down Expand Up @@ -93,7 +97,16 @@ export class PostgresDatabaseTreeItem extends AzExtParentTreeItem {
}

public async deleteTreeItemImpl(): Promise<void> {
const clientConfig = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName);
const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this.parent, this.databaseName);
await runPostgresQuery(clientConfig, `Drop Database ${wrapArgInQuotes(this.databaseName)};`);
}

private async showPasswordWarning(context: IActionContext): Promise<void> {
if (this.isShowingPasswordWarning) {
return;
}
this.isShowingPasswordWarning = true;
this.contextValue = createContextValue([PostgresDatabaseTreeItem.contextValue, "usesPassword"]);
await this.refresh(context);
}
}
4 changes: 2 additions & 2 deletions src/postgres/tree/PostgresServerTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export class PostgresServerTreeItem extends AzExtParentTreeItem {
} else if (this.partialConnectionString.databaseName) {
dbNames = [this.partialConnectionString.databaseName];
} else {
const clientConfig = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase);
const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, postgresDefaultDatabase);
const query = `SELECT datname FROM pg_catalog.pg_database WHERE datistemplate = false;`;
const queryResult = await runPostgresQuery(clientConfig, query);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
Expand Down Expand Up @@ -146,7 +146,7 @@ export class PostgresServerTreeItem extends AzExtParentTreeItem {
stepName: 'createPostgresDatabase',
validateInput: (name: string) => validateDatabaseName(name, getChildrenTask)
});
const clientConfig = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName);
const { clientConfig } = await PostgresClientConfigFactory.getClientConfigFromNode(this, databaseName);
context.showCreatingTreeItem(databaseName);
await runPostgresQuery(clientConfig, `Create Database ${wrapArgInQuotes(databaseName)};`);
return new PostgresDatabaseTreeItem(this, databaseName);
Expand Down

0 comments on commit a46e202

Please sign in to comment.