Fix broken native command line argument support (#23312)

This commit is contained in:
Cheena Malhotra
2023-06-07 00:37:49 -07:00
committed by GitHub
parent 9b94f82b2e
commit a1ab537094
4 changed files with 112 additions and 83 deletions

View File

@@ -30,64 +30,6 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
export interface SqlArgs {
/**
* Used to determine file paths to be opened with SQL Editor.
* If provided, we connect the given profile to to it.
* More than one files can be passed to connect to provided profile.
*/
_?: string[];
/**
* Provide authenticationType to be used.
* accepted values: AzureMFA, SqlLogin, Integrated, etc.
*/
authenticationType?: string
/**
* Name of database
*/
database?: string;
/**
* Name of server
*/
server?: string;
/**
* User name/email address
*/
user?: string;
/**
* Operation to perform:
* accepted values: connect, openConnectionDialog
*/
command?: string;
/**
* Name of connection provider,
* accepted values: mssql (by default), pgsql, etc.
*/
provider?: string;
/**
* Deprecated - used by SSMS - authenticationType should be used instead
*/
aad?: boolean;
/**
* Deprecated - used by SSMS - authenticationType should be used instead.
*/
integrated?: boolean;
/**
* Whether or not to show dashboard
* accepted values: true, false (by default).
*/
showDashboard?: boolean;
/**
* Supports providing applicationName that will be used for connection profile app name.
*/
applicationName?: string;
/**
* Supports providing advanced connection properties that providers support.
* Value must be a json object containing key-value pairs in format: '{"key1":"value1","key2":"value2",...}'
*/
connectionProperties?: string;
}
//#region decorators
type PathHandler = (uri: URI) => Promise<boolean>;
@@ -153,7 +95,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
// (null, commandName) => Launch the command with a null connection. If the command implementation needs a connection, it will need to create it.
// (serverName, null) => Connect object explorer and open a new query editor if no file names are passed. If file names are passed, connect their editors to the server.
// (null, null) => Prompt for a connection unless there are registered servers
public async processCommandLine(args: SqlArgs): Promise<void> {
public async processCommandLine(args: NativeParsedArgs): Promise<void> {
let profile: IConnectionProfile = undefined;
let commandName = undefined;
if (args) {
@@ -296,7 +238,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
return true;
}
private async confirmConnect(args: SqlArgs): Promise<boolean> {
private async confirmConnect(args: NativeParsedArgs): Promise<boolean> {
let detail = args && args.server ? localize('connectServerDetail', "This will connect to server {0}", args.server) : '';
const result = await this.dialogService.confirm({
message: localize('confirmConnect', "Are you sure you want to connect?"),
@@ -311,8 +253,8 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
return false;
}
private parseProtocolArgs(uri: URI): SqlArgs {
let args: SqlArgs = querystring.parse(uri.query);
private parseProtocolArgs(uri: URI): NativeParsedArgs {
let args: NativeParsedArgs = querystring.parse(uri.query);
// Clear out command, not supporting arbitrary command via this path
args.command = undefined;
return args;
@@ -336,7 +278,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
}
}
private readProfileFromArgs(args: SqlArgs) {
private readProfileFromArgs(args: NativeParsedArgs) {
let profile = new ConnectionProfile(this._capabilitiesService, null);
// We want connection store to use any matching password it finds
profile.savePassword = true;

View File

@@ -8,7 +8,7 @@ import * as TypeMoq from 'typemoq';
import * as azdata from 'azdata';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
import { CommandLineWorkbenchContribution, SqlArgs } from 'sql/workbench/contrib/commandLine/electron-browser/commandLine';
import { CommandLineWorkbenchContribution } from 'sql/workbench/contrib/commandLine/electron-browser/commandLine';
import * as Constants from 'sql/platform/connection/common/constants';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
@@ -35,11 +35,24 @@ import { FileQueryEditorInput } from 'sql/workbench/contrib/query/browser/fileQu
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
class TestParsedArgs implements NativeParsedArgs, SqlArgs {
class TestParsedArgs implements NativeParsedArgs {
[arg: string]: any;
_: string[];
database?: string;
// Start: SQL Args
aad?: boolean;
applicationName?: string;
authenticationType?: string;
command?: string;
connectionProperties?: string;
database?: string;
integrated?: boolean;
provider?: string;
server?: string;
showDashboard?: boolean;
user?: string;
// End: SQL Args
debugBrkPluginHost?: string;
debugBrkSearch?: string;
debugId?: string;
@@ -77,7 +90,6 @@ class TestParsedArgs implements NativeParsedArgs, SqlArgs {
'prof-startup'?: boolean;
'prof-startup-prefix'?: string;
'reuse-window'?: boolean;
server?: string;
'show-versions'?: boolean;
'skip-add-to-recently-opened'?: boolean;
'skip-getting-started'?: boolean;
@@ -87,16 +99,12 @@ class TestParsedArgs implements NativeParsedArgs, SqlArgs {
'uninstall-extension'?: string[];
'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch.
'upload-logs'?: string;
user?: string;
'user-data-dir'?: string;
_urls?: string[];
verbose?: boolean;
version?: boolean;
wait?: boolean;
waitMarkerFilePath?: string;
authenticationType?: string;
applicationName?: string;
connectionProperties?: string;
}
suite('commandLineService tests', () => {
@@ -220,6 +228,30 @@ suite('commandLineService tests', () => {
connectionManagementService.verifyAll();
});
test('processCommandLine shows dashboard when requested', async () => {
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
const args: TestParsedArgs = new TestParsedArgs();
args.server = 'myserver';
args.database = 'mydatabase';
args.user = 'myuser';
args.showDashboard = true;
args.authenticationType = Constants.AuthenticationType.SqlLogin;
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
connectionManagementService.setup(c => c.showDashboard(TypeMoq.It.isAny())).verifiable(TypeMoq.Times.atMostOnce());
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
connectionManagementService.setup(c => c.getConnectionGroups(TypeMoq.It.isAny())).returns(() => []);
let originalProfile: IConnectionProfile = undefined;
connectionManagementService.setup(c => c.getConnectionProfileById(TypeMoq.It.isAnyString())).returns(() => originalProfile);
const configurationService = getConfigurationServiceMock(true);
const logService = new NullLogService();
let contribution = getCommandLineContribution(connectionManagementService.object, configurationService.object, capabilitiesService, undefined, undefined, logService);
await contribution.processCommandLine(args);
connectionManagementService.verifyAll();
});
test('processCommandLine loads advanced options in args', async () => {
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
@@ -284,7 +316,6 @@ suite('commandLineService tests', () => {
test('processCommandLine invokes a command with a profile parameter when a server is passed', async () => {
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);