diff --git a/package.json b/package.json index f208b43757ac3..bd848e1d5bffe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.96.0", - "distro": "7ee3017d79a5ea3bc82111b770cf444010c72d3b", + "distro": "e769f8fbe1910f7c4af007cc8eeb764b7f924cfe", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/base/common/product.ts b/src/vs/base/common/product.ts index 35e396d595505..c7942d2c9cd18 100644 --- a/src/vs/base/common/product.ts +++ b/src/vs/base/common/product.ts @@ -105,7 +105,7 @@ export interface IProductConfiguration { readonly nlsBaseUrl: string; }; - readonly extensionPublisherMappings?: IStringDictionary; + readonly extensionPublisherOrgs?: readonly string[]; readonly extensionRecommendations?: IStringDictionary; readonly configBasedExtensionTips?: IStringDictionary; diff --git a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts index ee899383305c7..d78d2ef9c7332 100644 --- a/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts +++ b/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.ts @@ -70,7 +70,7 @@ export abstract class CommontExtensionManagementService extends Disposable imple } async canInstall(extension: IGalleryExtension): Promise { - const allowedToInstall = this.allowedExtensionsService.isAllowed({ id: extension.identifier.id }); + const allowedToInstall = this.allowedExtensionsService.isAllowed({ id: extension.identifier.id, publisherDisplayName: extension.publisherDisplayName }); if (allowedToInstall !== true) { return new MarkdownString(nls.localize('not allowed to install', "This extension cannot be installed because {0}", allowedToInstall.value)); } diff --git a/src/vs/platform/extensionManagement/common/allowedExtensionsService.ts b/src/vs/platform/extensionManagement/common/allowedExtensionsService.ts index ce978e5b430e4..0974d293a8d5f 100644 --- a/src/vs/platform/extensionManagement/common/allowedExtensionsService.ts +++ b/src/vs/platform/extensionManagement/common/allowedExtensionsService.ts @@ -33,7 +33,7 @@ export class AllowedExtensionsService extends Disposable implements IAllowedExte _serviceBrand: undefined; private allowedExtensions: AllowedExtensionsConfigValueType | undefined; - private readonly publisherMappings: IStringDictionary = {}; + private readonly publisherOrgs: string[]; private _onDidChangeAllowedExtensions = this._register(new Emitter()); readonly onDidChangeAllowedExtensions = this._onDidChangeAllowedExtensions.event; @@ -43,9 +43,7 @@ export class AllowedExtensionsService extends Disposable implements IAllowedExte @IConfigurationService protected readonly configurationService: IConfigurationService ) { super(); - for (const key in productService.extensionPublisherMappings) { - this.publisherMappings[key.toLowerCase()] = productService.extensionPublisherMappings[key].toLowerCase(); - } + this.publisherOrgs = productService.extensionPublisherOrgs?.map(p => p.toLowerCase()) ?? []; this.allowedExtensions = this.getAllowedExtensionsValue(); this._register(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(AllowedExtensionsConfigKey)) { @@ -67,24 +65,26 @@ export class AllowedExtensionsService extends Disposable implements IAllowedExte return Object.fromEntries(entries); } - isAllowed(extension: IGalleryExtension | IExtension | { id: string; version?: string; prerelease?: boolean; targetPlatform?: TargetPlatform }): true | IMarkdownString { + isAllowed(extension: IGalleryExtension | IExtension | { id: string; publisherDisplayName: string | undefined; version?: string; prerelease?: boolean; targetPlatform?: TargetPlatform }): true | IMarkdownString { if (!this.allowedExtensions) { return true; } - let id: string, version: string, targetPlatform: TargetPlatform, prerelease: boolean, publisher: string; + let id: string, version: string, targetPlatform: TargetPlatform, prerelease: boolean, publisher: string, publisherDisplayName: string | undefined; if (isGalleryExtension(extension)) { id = extension.identifier.id.toLowerCase(); version = extension.version; prerelease = extension.properties.isPreReleaseVersion; publisher = extension.publisher.toLowerCase(); + publisherDisplayName = extension.publisherDisplayName.toLowerCase(); targetPlatform = extension.properties.targetPlatform; } else if (isIExtension(extension)) { id = extension.identifier.id.toLowerCase(); version = extension.manifest.version; prerelease = extension.preRelease; publisher = extension.manifest.publisher.toLowerCase(); + publisherDisplayName = extension.publisherDisplayName?.toLowerCase(); targetPlatform = extension.targetPlatform; } else { id = extension.id.toLowerCase(); @@ -92,6 +92,7 @@ export class AllowedExtensionsService extends Disposable implements IAllowedExte targetPlatform = extension.targetPlatform ?? TargetPlatform.UNIVERSAL; prerelease = extension.prerelease ?? false; publisher = extension.id.substring(0, extension.id.indexOf('.')).toLowerCase(); + publisherDisplayName = extension.publisherDisplayName?.toLowerCase(); } const settingsCommandLink = URI.parse(`command:workbench.action.openSettings?${encodeURIComponent(JSON.stringify({ query: `@id:${AllowedExtensionsConfigKey}` }))}`).toString(); @@ -123,14 +124,14 @@ export class AllowedExtensionsService extends Disposable implements IAllowedExte return true; } - publisher = (this.publisherMappings[publisher])?.toLowerCase() ?? publisher; - const publisherValue = this.allowedExtensions[publisher]; + const publisherKey = publisherDisplayName && this.publisherOrgs.includes(publisherDisplayName) ? publisherDisplayName : publisher; + const publisherValue = this.allowedExtensions[publisherKey]; if (!isUndefined(publisherValue)) { if (isBoolean(publisherValue)) { - return publisherValue ? true : new MarkdownString(nls.localize('publisher not allowed', "the extensions from this publisher are not in the [allowed list]({1})", publisher, settingsCommandLink)); + return publisherValue ? true : new MarkdownString(nls.localize('publisher not allowed', "the extensions from this publisher are not in the [allowed list]({1})", publisherKey, settingsCommandLink)); } if (publisherValue === 'release' && prerelease) { - return new MarkdownString(nls.localize('prerelease versions from this publisher not allowed', "the pre-release versions from this publisher are not in the [allowed list]({1})", publisher, settingsCommandLink)); + return new MarkdownString(nls.localize('prerelease versions from this publisher not allowed', "the pre-release versions from this publisher are not in the [allowed list]({1})", publisherKey, settingsCommandLink)); } return true; } diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 21d4825480118..2fd54906e5eb1 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -782,7 +782,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi preRelease: !!extensionInfo.preRelease, compatible: !!options.compatible }); - if (!options.compatible || this.allowedExtensionsService.isAllowed({ id: extensionInfo.id }) === true) { + if (!options.compatible || this.allowedExtensionsService.isAllowed({ id: extensionInfo.id, publisherDisplayName: rawGalleryExtension.publisher.displayName }) === true) { toQuery.push(extensionInfo); } } @@ -806,7 +806,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi if (await this.isExtensionCompatible(extension, includePreRelease, targetPlatform)) { return extension; } - if (this.allowedExtensionsService.isAllowed({ id: extension.identifier.id }) !== true) { + if (this.allowedExtensionsService.isAllowed({ id: extension.identifier.id, publisherDisplayName: extension.publisherDisplayName }) !== true) { return null; } const query = new Query() @@ -861,7 +861,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi return areApiProposalsCompatible(enabledApiProposals); } - private async isValidVersion(extension: string, rawGalleryExtensionVersion: IRawGalleryExtensionVersion, versionType: 'release' | 'prerelease' | 'any', compatible: boolean, allTargetPlatforms: TargetPlatform[], targetPlatform: TargetPlatform, productVersion: IProductVersion = { version: this.productService.version, date: this.productService.date }): Promise { + private async isValidVersion(extension: string, rawGalleryExtensionVersion: IRawGalleryExtensionVersion, publisherDisplayName: string, versionType: 'release' | 'prerelease' | 'any', compatible: boolean, allTargetPlatforms: TargetPlatform[], targetPlatform: TargetPlatform, productVersion: IProductVersion = { version: this.productService.version, date: this.productService.date }): Promise { const targetPlatformForExtension = getTargetPlatformForExtensionVersion(rawGalleryExtensionVersion); if (!isTargetPlatformCompatible(targetPlatformForExtension, allTargetPlatforms, targetPlatform)) { return false; @@ -872,7 +872,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi } if (compatible) { - if (this.allowedExtensionsService.isAllowed({ id: extension, version: rawGalleryExtensionVersion.version, prerelease: versionType === 'any' ? undefined : isPreReleaseVersion(rawGalleryExtensionVersion), targetPlatform: targetPlatformForExtension }) !== true) { + if (this.allowedExtensionsService.isAllowed({ id: extension, publisherDisplayName, version: rawGalleryExtensionVersion.version, prerelease: versionType === 'any' ? undefined : isPreReleaseVersion(rawGalleryExtensionVersion), targetPlatform: targetPlatformForExtension }) !== true) { return false; } try { @@ -1015,7 +1015,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi * Skip if the extension is not allowed. * All versions are not needed in this case */ - if (this.allowedExtensionsService.isAllowed({ id: extensionIdentifier.id }) !== true) { + if (this.allowedExtensionsService.isAllowed({ id: extensionIdentifier.id, publisherDisplayName: rawGalleryExtension.publisher.displayName }) !== true) { continue; } } @@ -1081,6 +1081,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi if (await this.isValidVersion( extensionIdentifier.id, rawGalleryExtensionVersion, + rawGalleryExtension.publisher.displayName, includePreRelease ? 'any' : 'release', criteria.compatible, allTargetPlatforms, @@ -1416,7 +1417,9 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi if ( (await this.isValidVersion( extensionIdentifier.id, - version, includePreRelease ? 'any' : 'release', + version, + galleryExtensions[0].publisher.displayName, + includePreRelease ? 'any' : 'release', true, allTargetPlatforms, targetPlatform)) diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index ecfa0c9985c89..2d6713d409d09 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -634,7 +634,9 @@ export interface IAllowedExtensionsService { readonly _serviceBrand: undefined; readonly onDidChangeAllowedExtensions: Event; - isAllowed(extension: IGalleryExtension | IExtension | { id: string; version?: string; prerelease?: boolean }): true | IMarkdownString; + + isAllowed(extension: IGalleryExtension | IExtension): true | IMarkdownString; + isAllowed(extension: { id: string; publisherDisplayName: string | undefined; version?: string; prerelease?: boolean; targetPlatform?: TargetPlatform }): true | IMarkdownString; } export async function computeSize(location: URI, fileService: IFileService): Promise { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 7abeae6b2e6d9..a55978c612f26 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -152,7 +152,7 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", extensionId, this.productService.version)); } - const allowedToInstall = this.allowedExtensionsService.isAllowed({ id: extensionId, version: manifest.version }); + const allowedToInstall = this.allowedExtensionsService.isAllowed({ id: extensionId, version: manifest.version, publisherDisplayName: undefined }); if (allowedToInstall !== true) { throw new Error(nls.localize('notAllowed', "This extension cannot be installed because {0}", allowedToInstall.value)); } diff --git a/src/vs/platform/extensionManagement/test/common/allowedExtensionsService.test.ts b/src/vs/platform/extensionManagement/test/common/allowedExtensionsService.test.ts index a9c68485dfbcf..9f522a6c832bc 100644 --- a/src/vs/platform/extensionManagement/test/common/allowedExtensionsService.test.ts +++ b/src/vs/platform/extensionManagement/test/common/allowedExtensionsService.test.ts @@ -8,7 +8,6 @@ import { AllowedExtensionsService } from '../../common/allowedExtensionsService. import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js'; import { IProductService } from '../../../product/common/productService.js'; import { TestConfigurationService } from '../../../configuration/test/common/testConfigurationService.js'; -import { IStringDictionary } from '../../../../base/common/collections.js'; import { AllowedExtensionsConfigKey, IGalleryExtension, ILocalExtension } from '../../common/extensionManagement.js'; import { ExtensionType, IExtensionManifest, TargetPlatform } from '../../../extensions/common/extensions.js'; import { Event } from '../../../../base/common/event.js'; @@ -29,157 +28,157 @@ suite('AllowedExtensionsService', () => { test('should allow all extensions if no allowed extensions are configured', () => { const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, true); }); test('should not allow specific extension if not in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': false }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, false); }); test('should allow specific extension if in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': true }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, true); }); test('should not allow pre-release extension if only release is allowed', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': 'release' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', prerelease: true }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, prerelease: true }) === true, false); }); test('should allow pre-release extension if pre-release is allowed', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': true }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', prerelease: true }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, prerelease: true }) === true, true); }); test('should allow specific version of an extension when configured to that version', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3' }) === true, true); }); test('should allow any version of an extension when a specific version is configured', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, true); }); test('should allow any version of an extension when release is configured', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': 'release' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, true); }); test('should allow a version of an extension when release is configured', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': 'release' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3' }) === true, true); }); test('should allow a pre-release version of an extension when release is configured', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': 'release' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3', prerelease: true }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3', prerelease: true }) === true, false); }); test('should allow specific version of an extension when configured to multiple versions', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3', '2.0.1', '3.1.2'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3' }) === true, true); }); test('should allow platform specific version of an extension when configured to platform specific version', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3@darwin-x64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_X64 }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_X64 }) === true, true); }); test('should allow universal platform specific version of an extension when configured to platform specific version', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3@darwin-x64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3', targetPlatform: TargetPlatform.UNIVERSAL }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3', targetPlatform: TargetPlatform.UNIVERSAL }) === true, true); }); test('should allow specific version of an extension when configured to platform specific version', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3@darwin-x64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3' }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3' }) === true, true); }); test('should allow platform specific version of an extension when configured to multiple versions', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.0.0', '1.2.3@darwin-x64', '1.2.3@darwin-arm64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_X64 }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_X64 }) === true, true); }); test('should not allow platform specific version of an extension when configured to different platform specific version', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.2.3@darwin-x64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_ARM64 }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.2.3', targetPlatform: TargetPlatform.DARWIN_ARM64 }) === true, false); }); test('should specific version of an extension when configured to different versions', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test.extension': ['1.0.0', '1.2.3@darwin-x64', '1.2.3@darwin-arm64'] }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', version: '1.0.1' }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, version: '1.0.1' }) === true, false); }); test('should allow extension if publisher is in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test': true }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }), true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }), true); }); test('should allow extension if publisher is not in allowed list and has publisher mapping', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'hello': true }); - const testObject = disposables.add(new AllowedExtensionsService(aProductService({ 'test': 'hello' }), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }), true); + const testObject = disposables.add(new AllowedExtensionsService(aProductService(['hello']), configurationService)); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: 'Hello' }), true); }); test('should allow extension if publisher is not in allowed list and has different publisher mapping', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'hello': true }); - const testObject = disposables.add(new AllowedExtensionsService(aProductService({ 'test': 'bar' }), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, false); + const testObject = disposables.add(new AllowedExtensionsService(aProductService(['bar']), configurationService)); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: 'Hello' }) === true, false); }); test('should not allow extension if publisher is not in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test': false }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, false); }); test('should not allow prerelease extension if publisher is allowed only to release', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test': 'release' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', prerelease: true }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, prerelease: true }) === true, false); }); test('should allow extension if publisher is set to random value', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { 'test': 'hello' }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension', prerelease: true }) === true, true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined, prerelease: true }) === true, true); }); test('should allow extension if only wildcard is in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { '*': true }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }), true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }), true); }); test('should allow extension if wildcard is in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { '*': true, 'hello': false }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }), true); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }), true); }); test('should not allow extension if wildcard is not in allowed list', () => { configurationService.setUserConfiguration(AllowedExtensionsConfigKey, { '*': false, 'hello': true }); const testObject = disposables.add(new AllowedExtensionsService(aProductService(), configurationService)); - assert.strictEqual(testObject.isAllowed({ id: 'test.extension' }) === true, false); + assert.strictEqual(testObject.isAllowed({ id: 'test.extension', publisherDisplayName: undefined }) === true, false); }); test('should allow a gallery extension', () => { @@ -202,15 +201,15 @@ suite('AllowedExtensionsService', () => { await promise; }); - function aProductService(extensionPublisherMappings?: IStringDictionary): IProductService { + function aProductService(extensionPublisherOrgs?: string[]): IProductService { return { _serviceBrand: undefined, - extensionPublisherMappings + extensionPublisherOrgs } as IProductService; } function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}): IGalleryExtension { - const galleryExtension = Object.create({ type: 'gallery', name, publisher: 'pub', version: '1.0.0', allTargetPlatforms: [TargetPlatform.UNIVERSAL], properties: {}, assets: {}, isSigned: true, ...properties }); + const galleryExtension = Object.create({ type: 'gallery', name, publisher: 'pub', publisherDisplayName: 'Pub', version: '1.0.0', allTargetPlatforms: [TargetPlatform.UNIVERSAL], properties: {}, assets: {}, isSigned: true, ...properties }); galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], ...galleryExtensionProperties }; galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; return galleryExtension; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index aeb14afeb98d6..196334c29243d 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -441,7 +441,7 @@ export class InstallAction extends ExtensionAction { if (this.extension.state !== ExtensionState.Uninstalled) { return; } - if (this.options.installPreReleaseVersion && (!this.extension.hasPreReleaseVersion || this.allowedExtensionsService.isAllowed({ id: this.extension.identifier.id, prerelease: true }) !== true)) { + if (this.options.installPreReleaseVersion && (!this.extension.hasPreReleaseVersion || this.allowedExtensionsService.isAllowed({ id: this.extension.identifier.id, publisherDisplayName: this.extension.publisherDisplayName, prerelease: true }) !== true)) { return; } if (!this.options.installPreReleaseVersion && !this.extension.hasReleaseVersion) { @@ -1040,6 +1040,7 @@ export class ToggleAutoUpdateForExtensionAction extends ExtensionAction { if (this.extension.deprecationInfo?.disallowInstall) { return; } + const extension = this.extension.local ?? this.extension.gallery; if (extension && this.allowedExtensionsService.isAllowed(extension) !== true) { return; @@ -1250,8 +1251,8 @@ async function getContextMenuActionsGroups(extension: IExtension | undefined | n cksOverlay.push(['extensionHasPreReleaseVersion', extension.hasPreReleaseVersion]); cksOverlay.push(['extensionHasReleaseVersion', extension.hasReleaseVersion]); cksOverlay.push(['extensionDisallowInstall', !!extension.deprecationInfo?.disallowInstall]); - cksOverlay.push(['isExtensionAllowed', allowedExtensionsService.isAllowed({ id: extension.identifier.id }) === true]); - cksOverlay.push(['isPreReleaseExtensionAllowed', allowedExtensionsService.isAllowed({ id: extension.identifier.id, prerelease: true }) === true]); + cksOverlay.push(['isExtensionAllowed', allowedExtensionsService.isAllowed({ id: extension.identifier.id, publisherDisplayName: extension.publisherDisplayName }) === true]); + cksOverlay.push(['isPreReleaseExtensionAllowed', allowedExtensionsService.isAllowed({ id: extension.identifier.id, publisherDisplayName: extension.publisherDisplayName, prerelease: true }) === true]); cksOverlay.push(['extensionIsUnsigned', extension.gallery && !extension.gallery.isSigned]); const [colorThemes, fileIconThemes, productIconThemes, extensionUsesAuth] = await Promise.all([workbenchThemeService.getColorThemes(), workbenchThemeService.getFileIconThemes(), workbenchThemeService.getProductIconThemes(), authenticationUsageService.extensionUsesAuth(extension.identifier.id.toLowerCase())]);