mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
add ADS checks back to install extension workflow (#15320)
This commit is contained in:
@@ -61,7 +61,7 @@ import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensi
|
|||||||
import { Schemas } from 'vs/base/common/network';
|
import { Schemas } from 'vs/base/common/network';
|
||||||
import { ShowRuntimeExtensionsAction } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor';
|
import { ShowRuntimeExtensionsAction } from 'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor';
|
||||||
import { clearSearchResultsIcon, configureRecommendedIcon, extensionsViewIcon, filterIcon, installWorkspaceRecommendedIcon, refreshIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
import { clearSearchResultsIcon, configureRecommendedIcon, extensionsViewIcon, filterIcon, installWorkspaceRecommendedIcon, refreshIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
||||||
import { ExtensionsPolicy, EXTENSION_CATEGORIES } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionsPolicy, ExtensionsPolicyKey, EXTENSION_CATEGORIES } from 'vs/platform/extensions/common/extensions';
|
||||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { isArray } from 'vs/base/common/types';
|
import { isArray } from 'vs/base/common/types';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
@@ -69,6 +69,7 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
|||||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||||
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
|
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
|
||||||
import { Promises } from 'vs/base/common/async';
|
import { Promises } from 'vs/base/common/async';
|
||||||
|
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||||
|
|
||||||
// Singletons
|
// Singletons
|
||||||
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
|
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
|
||||||
@@ -626,6 +627,15 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}} - extension policy check function
|
||||||
|
const isExtensionInstallationAllowed = (configurationService: IConfigurationService, notificationService: INotificationService): boolean => {
|
||||||
|
const allowAll = configurationService.getValue<string>(ExtensionsPolicyKey) === ExtensionsPolicy.allowAll;
|
||||||
|
if (!allowAll) {
|
||||||
|
this.notificationService.error(localize('InstallVSIXAction.allowNone', 'Your extension policy does not allow installing extensions. Please change your extension policy and try again.'));
|
||||||
|
}
|
||||||
|
return allowAll;
|
||||||
|
};
|
||||||
|
|
||||||
this.registerExtensionAction({
|
this.registerExtensionAction({
|
||||||
id: SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID,
|
id: SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID,
|
||||||
title: { value: localize('InstallFromVSIX', "Install from VSIX..."), original: 'Install from VSIX...' },
|
title: { value: localize('InstallFromVSIX', "Install from VSIX..."), original: 'Install from VSIX...' },
|
||||||
@@ -642,6 +652,14 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
|
|||||||
run: async (accessor: ServicesAccessor) => {
|
run: async (accessor: ServicesAccessor) => {
|
||||||
const fileDialogService = accessor.get(IFileDialogService);
|
const fileDialogService = accessor.get(IFileDialogService);
|
||||||
const commandService = accessor.get(ICommandService);
|
const commandService = accessor.get(ICommandService);
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}} - add policy check
|
||||||
|
const configurationService = accessor.get(IConfigurationService);
|
||||||
|
const notificationService = accessor.get(INotificationService);
|
||||||
|
if (!isExtensionInstallationAllowed(configurationService, notificationService)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const vsixPaths = await fileDialogService.showOpenDialog({
|
const vsixPaths = await fileDialogService.showOpenDialog({
|
||||||
title: localize('installFromVSIX', "Install from VSIX"),
|
title: localize('installFromVSIX', "Install from VSIX"),
|
||||||
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
||||||
@@ -669,12 +687,56 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
|
|||||||
const hostService = accessor.get(IHostService);
|
const hostService = accessor.get(IHostService);
|
||||||
const notificationService = accessor.get(INotificationService);
|
const notificationService = accessor.get(INotificationService);
|
||||||
|
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}} - added policy check and third party extension confirmation.
|
||||||
|
const storageService = accessor.get(IStorageService);
|
||||||
|
const configurationService = accessor.get(IConfigurationService);
|
||||||
|
if (!isExtensionInstallationAllowed(configurationService, notificationService)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const extensions = Array.isArray(resources) ? resources : [resources];
|
const extensions = Array.isArray(resources) ? resources : [resources];
|
||||||
await Promises.settled(extensions.map(async (vsix) => await extensionsWorkbenchService.install(vsix)))
|
await Promises.settled(extensions.map(async (vsix) => {
|
||||||
|
if (!storageService.getBoolean(vsix.fsPath, StorageScope.GLOBAL)) {
|
||||||
|
const accept = await new Promise<boolean>(resolve => {
|
||||||
|
this.notificationService.prompt(
|
||||||
|
Severity.Warning,
|
||||||
|
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: localize('thirdPartExt.yes', 'Yes'),
|
||||||
|
run: () => resolve(true)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: localize('thirdPartyExt.no', 'No'),
|
||||||
|
run: () => resolve(false)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
|
||||||
|
isSecondary: true,
|
||||||
|
run: () => {
|
||||||
|
storageService.store(vsix.fsPath, true, StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
{ sticky: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!accept) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return await extensionsWorkbenchService.install(vsix);
|
||||||
|
}))
|
||||||
.then(async (extensions) => {
|
.then(async (extensions) => {
|
||||||
for (const extension of extensions) {
|
for (const extension of extensions) {
|
||||||
|
// {{SQL CARBON EDIT}} - Add null check
|
||||||
|
if (extension === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const requireReload = !(extension.local && extensionService.canAddExtension(toExtensionDescription(extension.local)));
|
const requireReload = !(extension.local && extensionService.canAddExtension(toExtensionDescription(extension.local)));
|
||||||
const message = requireReload ? localize('InstallVSIXAction.successReload', "Completed installing {0} extension from VSIX. Please reload Visual Studio Code to enable it.", extension.displayName || extension.name)
|
const message = requireReload ? localize('InstallVSIXAction.successReload', "Completed installing {0} extension from VSIX. Please reload Azure Data Studio to enable it.", extension.displayName || extension.name) // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
|
||||||
: localize('InstallVSIXAction.success', "Completed installing {0} extension from VSIX.", extension.displayName || extension.name);
|
: localize('InstallVSIXAction.success', "Completed installing {0} extension from VSIX.", extension.displayName || extension.name);
|
||||||
const actions = requireReload ? [{
|
const actions = requireReload ? [{
|
||||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { IGalleryExtension, IExtensionGalleryService, INSTALL_ERROR_MALICIOUS, I
|
|||||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensioManagementService, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensioManagementService, IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||||
import { ExtensionRecommendationReason, IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
import { ExtensionRecommendationReason, IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, IExtensionManifest, isLanguagePackExtension, ExtensionsPolicy, ExtensionsPolicyKey } from 'vs/platform/extensions/common/extensions'; // {{SQL CARBON EDIT}}
|
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, IExtensionManifest, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions'; // {{SQL CARBON EDIT}}
|
||||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||||
import { IFileService, IFileContent } from 'vs/platform/files/common/files';
|
import { IFileService, IFileContent } from 'vs/platform/files/common/files';
|
||||||
@@ -48,7 +48,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
|
|||||||
import { prefersExecuteOnUI, prefersExecuteOnWorkspace, canExecuteOnUI, canExecuteOnWorkspace, prefersExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
import { prefersExecuteOnUI, prefersExecuteOnWorkspace, canExecuteOnUI, canExecuteOnWorkspace, prefersExecuteOnWeb } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||||
import { IProductService } from 'vs/platform/product/common/productService';
|
import { IProductService } from 'vs/platform/product/common/productService';
|
||||||
import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||||
import { IActionViewItemOptions, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
import { IActionViewItemOptions, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||||
import { EXTENSIONS_CONFIG, IExtensionsConfigContent } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
import { EXTENSIONS_CONFIG, IExtensionsConfigContent } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
||||||
@@ -59,9 +59,6 @@ import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
|
|||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import * as Constants from 'vs/workbench/contrib/logs/common/logConstants';
|
import * as Constants from 'vs/workbench/contrib/logs/common/logConstants';
|
||||||
import { infoIcon, manageExtensionIcon, syncEnabledIcon, syncIgnoredIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
import { infoIcon, manageExtensionIcon, syncEnabledIcon, syncIgnoredIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
||||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; // {{SQL CARBON EDIT}}
|
|
||||||
import product from 'vs/platform/product/common/product';
|
|
||||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
|
||||||
|
|
||||||
function getRelativeDateLabel(date: Date): string {
|
function getRelativeDateLabel(date: Date): string {
|
||||||
const delta = new Date().getTime() - date.getTime();
|
const delta = new Date().getTime() - date.getTime();
|
||||||
@@ -2373,110 +2370,6 @@ export class EnableAllWorkspaceAction extends Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InstallVSIXAction extends Action {
|
|
||||||
|
|
||||||
static readonly ID = 'workbench.extensions.action.installVSIX';
|
|
||||||
static readonly LABEL = localize('installVSIX', "Install from VSIX...");
|
|
||||||
static readonly AVAILABLE = !(product.disabledFeatures && product.disabledFeatures.indexOf(InstallVSIXAction.ID) >= 0); // {{SQL CARBON EDIT}} add available logic
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
id = InstallVSIXAction.ID,
|
|
||||||
label = InstallVSIXAction.LABEL,
|
|
||||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
|
||||||
@INotificationService private readonly notificationService: INotificationService,
|
|
||||||
@IHostService private readonly hostService: IHostService,
|
|
||||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
|
||||||
@IExtensionService private readonly extensionService: IExtensionService,
|
|
||||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService, // {{SQL CARBON EDIT}}
|
|
||||||
@IStorageService private storageService: IStorageService
|
|
||||||
) {
|
|
||||||
super(id, label, 'extension-action install-vsix', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(vsixPaths?: URI[]): Promise<void> {
|
|
||||||
// {{SQL CARBON EDIT}} - Replace run body
|
|
||||||
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
|
||||||
if (extensionPolicy === ExtensionsPolicy.allowAll) {
|
|
||||||
if (!vsixPaths) {
|
|
||||||
vsixPaths = await this.fileDialogService.showOpenDialog({
|
|
||||||
title: localize('installFromVSIX', "Install from VSIX"),
|
|
||||||
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
|
||||||
canSelectFiles: true,
|
|
||||||
canSelectMany: true,
|
|
||||||
openLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!vsixPaths) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(vsixPaths.map(async vsix => {
|
|
||||||
if (!this.storageService.getBoolean(vsix.fsPath, StorageScope.GLOBAL)) {
|
|
||||||
const accept = await new Promise<boolean>(resolve => {
|
|
||||||
this.notificationService.prompt(
|
|
||||||
Severity.Warning,
|
|
||||||
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
|
|
||||||
[
|
|
||||||
{
|
|
||||||
label: localize('thirdPartExt.yes', 'Yes'),
|
|
||||||
run: () => resolve(true)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: localize('thirdPartyExt.no', 'No'),
|
|
||||||
run: () => resolve(false)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
|
|
||||||
isSecondary: true,
|
|
||||||
run: () => {
|
|
||||||
this.storageService.store(vsix.fsPath, true, StorageScope.GLOBAL, StorageTarget.MACHINE);
|
|
||||||
resolve(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
{ sticky: true }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!accept) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.extensionsWorkbenchService.install(vsix);
|
|
||||||
})).then(async (extensions) => {
|
|
||||||
for (const extension of extensions) {
|
|
||||||
if (!extension) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const requireReload = !(extension.local && this.extensionService.canAddExtension(toExtensionDescription(extension.local)));
|
|
||||||
const message = requireReload ? localize('InstallVSIXAction.successReload', "Please reload Azure Data Studio to complete installing the extension {0}.", extension.displayName || extension.name) // {{SQL CARBON EDIT}}
|
|
||||||
: localize('InstallVSIXAction.success', "Completed installing the extension {0}.", extension.displayName || extension.name);
|
|
||||||
const actions = requireReload ? [{
|
|
||||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
|
||||||
run: () => this.hostService.reload()
|
|
||||||
}] : [];
|
|
||||||
this.notificationService.prompt(
|
|
||||||
Severity.Info,
|
|
||||||
message,
|
|
||||||
actions,
|
|
||||||
{ sticky: true }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, ShowInstalledExtensionsAction.LABEL).run();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.notificationService.error(localize('InstallVSIXAction.allowNone', 'Your extension policy does not allow downloading extensions. Please change your extension policy and try again.'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get enabled(): boolean { // {{SQL CARBON EDIT}} add enabled logic
|
|
||||||
return InstallVSIXAction.AVAILABLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ReinstallAction extends Action {
|
export class ReinstallAction extends Action {
|
||||||
|
|
||||||
static readonly ID = 'workbench.extensions.action.reinstall';
|
static readonly ID = 'workbench.extensions.action.reinstall';
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat
|
|||||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||||
|
|
||||||
// eslint-disable-next-line code-import-patterns
|
// eslint-disable-next-line code-import-patterns
|
||||||
import { InstallVSIXAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; // {{SQL CARBON EDIT}} add import
|
import { SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
(function registerActions(): void {
|
(function registerActions(): void {
|
||||||
@@ -99,15 +99,15 @@ import { InstallVSIXAction } from 'vs/workbench/contrib/extensions/browser/exten
|
|||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
(function registerMenu(): void {
|
(function registerMenu(): void {
|
||||||
if (InstallVSIXAction.AVAILABLE) {
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { // {{SQL CARBON EDIT}} - Add install VSIX menu item
|
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { // {{SQL CARBON EDIT}} - Add install VSIX menu item
|
||||||
group: '5.1_installExtension',
|
group: '5.1_installExtension',
|
||||||
command: {
|
command: {
|
||||||
id: InstallVSIXAction.ID,
|
id: SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID,
|
||||||
title: localize({ key: 'miinstallVsix', comment: ['&& denotes a mnemonic'] }, "Install Extension from VSIX Package")
|
title: localize({ key: 'miinstallVsix', comment: ['&& denotes a mnemonic'] }, "Install Extension from VSIX Package")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
|
MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, {
|
||||||
group: '6_close',
|
group: '6_close',
|
||||||
|
|||||||
Reference in New Issue
Block a user