diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts index 51f0635bd5..2ea87124af 100644 --- a/extensions/sql-database-projects/src/common/constants.ts +++ b/extensions/sql-database-projects/src/common/constants.ts @@ -538,6 +538,7 @@ export const hostFileName = 'host.json'; export const sqlExtensionPackageName = 'Microsoft.Azure.WebJobs.Extensions.Sql'; export const placeHolderObject = '[dbo].[table1]'; export const sqlBindingsHelpLink = 'https://github.com/Azure/azure-functions-sql-extension/blob/main/README.md'; +export const passwordPlaceholder = '******'; export const input = localize('input', "Input"); export const output = localize('output', "Output"); @@ -570,4 +571,9 @@ export const connectionProfile = localize('connectionProfile', 'Select a connect export const userConnectionString = localize('userConnectionString', 'Enter connection string'); export const selectConnectionString = localize('selectConnectionString', 'Select SQL connection string method'); export const selectConnectionError = (err?: any) => err ? localize('selectConnectionError', "Failed to set connection string app setting: {0}", utils.getErrorMessage(err)) : localize('unableToSetConnectionString', "Failed to set connection string app setting"); - +export const includePassword = localize('includePassword', 'Do you want to include the password from this connection in your local.settings.json file?'); +export const enterPasswordPrompt = localize('enterPasswordPrompt', 'Enter the password to be used for the connection string'); +export const enterPasswordManually = localize('enterPasswordManually', 'Enter password or press escape to cancel'); +export const userPasswordLater = localize('userPasswordLater', 'In order to user the SQL connection string later you will need to manually enter the password in your local.settings.json file.'); +export const openFile = localize('openFile', "Open File"); +export const closeButton = localize('closeButton', "Close"); diff --git a/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts b/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts index c5c8ca3ffb..15f7a3bc94 100644 --- a/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts +++ b/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import { BindingType } from 'vscode-mssql'; +import { BindingType, IConnectionInfo } from 'vscode-mssql'; import * as constants from '../common/constants'; import * as utils from '../common/utils'; import * as azureFunctionsUtils from '../common/azureFunctionsUtils'; @@ -167,6 +167,8 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined, } let connectionString: string = ''; + let includePassword: string | undefined; + let connectionInfo: IConnectionInfo | undefined; if (selectedConnectionStringMethod === constants.userConnectionString) { // User chooses to enter connection string manually connectionString = await vscode.window.showInputBox( @@ -180,7 +182,7 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined, } else { // Let user choose from existing connections to create connection string from let connectionUri: string = ''; - const connectionInfo = await vscodeMssqlApi.promptForConnection(true); + connectionInfo = await vscodeMssqlApi.promptForConnection(true); if (!connectionInfo) { // User cancelled return to selectedConnectionStringMethod prompt continue; @@ -194,7 +196,22 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined, continue; } try { - connectionString = await vscodeMssqlApi.getConnectionString(connectionUri, false, false); + // Prompt to include password in connection string if authentication type is SqlLogin and connection has password saved + if (connectionInfo.authenticationType === 'SqlLogin' && connectionInfo.password) { + includePassword = await vscode.window.showQuickPick([constants.yesString, constants.noString], { + title: constants.includePassword, + canPickMany: false, + ignoreFocusOut: true + }); + if (includePassword === constants.yesString) { + // set connection string to include password + connectionString = await vscodeMssqlApi.getConnectionString(connectionUri, true, false); + } + } + // set connection string to not include the password if connection info does not include password, or user chooses to not include password, or authentication type is not sql login + if (includePassword !== constants.yesString) { + connectionString = await vscodeMssqlApi.getConnectionString(connectionUri, false, false); + } } catch (e) { // failed to get connection string for selected connection and will go back to prompt for connection string methods console.warn(e); @@ -204,7 +221,33 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined, } if (connectionString) { try { - const success = await azureFunctionsUtils.setLocalAppSetting(path.dirname(projectUri.fsPath), newConnectionStringSettingName, connectionString); + const projectFolder: string = path.dirname(projectUri.fsPath); + const localSettingsPath: string = path.join(projectFolder, constants.azureFunctionLocalSettingsFileName); + let userPassword: string | undefined; + // Ask user to enter password if auth type is sql login and password is not saved + if (connectionInfo?.authenticationType === 'SqlLogin' && !connectionInfo?.password) { + userPassword = await vscode.window.showInputBox({ + prompt: constants.enterPasswordPrompt, + placeHolder: constants.enterPasswordManually, + ignoreFocusOut: true, + password: true, + validateInput: input => input ? undefined : constants.valueMustNotBeEmpty + }); + if (userPassword) { + // if user enters password replace password placeholder with user entered password + connectionString = connectionString.replace(constants.passwordPlaceholder, userPassword); + } + } + if (includePassword !== constants.yesString && !userPassword && connectionInfo?.authenticationType === 'SqlLogin') { + // if user does not want to include password or user does not enter password, show warning message that they will have to enter it manually later in local.settings.json + void vscode.window.showWarningMessage(constants.userPasswordLater, constants.openFile, constants.closeButton).then(async (result) => { + if (result === constants.openFile) { + // open local.settings.json file + void vscode.commands.executeCommand(constants.vscodeOpenCommand, vscode.Uri.file(localSettingsPath)); + } + }); + } + const success = await azureFunctionsUtils.setLocalAppSetting(projectFolder, newConnectionStringSettingName, connectionString); if (success) { // exit both loops and insert binding connectionStringSettingName = newConnectionStringSettingName;