Modularize the policy generation script (#272332)

This commit is contained in:
Paul
2025-10-21 17:08:32 -07:00
committed by GitHub
parent f0d0e4302e
commit 0ea6a23376
39 changed files with 6165 additions and 1231 deletions
+57
View File
@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const render_1 = require("./render");
class BasePolicy {
type;
name;
category;
minimumVersion;
description;
moduleName;
constructor(type, name, category, minimumVersion, description, moduleName) {
this.type = type;
this.name = name;
this.category = category;
this.minimumVersion = minimumVersion;
this.description = description;
this.moduleName = moduleName;
}
renderADMLString(nlsString, translations) {
return (0, render_1.renderADMLString)(this.name, this.moduleName, nlsString, translations);
}
renderADMX(regKey) {
return [
`<policy name="${this.name}" class="Both" displayName="$(string.${this.name})" explainText="$(string.${this.name}_${this.description.nlsKey.replace(/\./g, '_')})" key="Software\\Policies\\Microsoft\\${regKey}" presentation="$(presentation.${this.name})">`,
` <parentCategory ref="${this.category.name.nlsKey}" />`,
` <supportedOn ref="Supported_${this.minimumVersion.replace(/\./g, '_')}" />`,
` <elements>`,
...this.renderADMXElements(),
` </elements>`,
`</policy>`
];
}
renderADMLStrings(translations) {
return [
`<string id="${this.name}">${this.name}</string>`,
this.renderADMLString(this.description, translations)
];
}
renderADMLPresentation() {
return `<presentation id="${this.name}">${this.renderADMLPresentationContents()}</presentation>`;
}
renderProfile() {
return [`<key>${this.name}</key>`, this.renderProfileValue()];
}
renderProfileManifest(translations) {
return `<dict>
${this.renderProfileManifestValue(translations)}
</dict>`;
}
}
exports.BasePolicy = BasePolicy;
//# sourceMappingURL=basePolicy.js.map
+62
View File
@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { renderADMLString } from './render';
import { Category, LanguageTranslations, NlsString, Policy, PolicyType } from './types';
export abstract class BasePolicy implements Policy {
constructor(
readonly type: PolicyType,
readonly name: string,
readonly category: Category,
readonly minimumVersion: string,
protected description: NlsString,
protected moduleName: string,
) { }
protected renderADMLString(nlsString: NlsString, translations?: LanguageTranslations): string {
return renderADMLString(this.name, this.moduleName, nlsString, translations);
}
renderADMX(regKey: string) {
return [
`<policy name="${this.name}" class="Both" displayName="$(string.${this.name})" explainText="$(string.${this.name}_${this.description.nlsKey.replace(/\./g, '_')})" key="Software\\Policies\\Microsoft\\${regKey}" presentation="$(presentation.${this.name})">`,
` <parentCategory ref="${this.category.name.nlsKey}" />`,
` <supportedOn ref="Supported_${this.minimumVersion.replace(/\./g, '_')}" />`,
` <elements>`,
...this.renderADMXElements(),
` </elements>`,
`</policy>`
];
}
protected abstract renderADMXElements(): string[];
renderADMLStrings(translations?: LanguageTranslations) {
return [
`<string id="${this.name}">${this.name}</string>`,
this.renderADMLString(this.description, translations)
];
}
renderADMLPresentation(): string {
return `<presentation id="${this.name}">${this.renderADMLPresentationContents()}</presentation>`;
}
protected abstract renderADMLPresentationContents(): string;
renderProfile() {
return [`<key>${this.name}</key>`, this.renderProfileValue()];
}
renderProfileManifest(translations?: LanguageTranslations): string {
return `<dict>
${this.renderProfileManifestValue(translations)}
</dict>`;
}
abstract renderProfileValue(): string;
abstract renderProfileManifestValue(translations?: LanguageTranslations): string;
}
+49
View File
@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BooleanPolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const basePolicy_1 = require("./basePolicy");
const render_1 = require("./render");
const types_1 = require("./types");
class BooleanPolicy extends basePolicy_1.BasePolicy {
static from(category, policy) {
const { name, minimumVersion, localization, type } = policy;
if (type !== 'boolean') {
return undefined;
}
return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(types_1.PolicyType.Boolean, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [
`<boolean id="${this.name}" valueName="${this.name}">`,
` <trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>`,
`</boolean>`
];
}
renderADMLPresentationContents() {
return `<checkBox refId="${this.name}">${this.name}</checkBox>`;
}
renderProfileValue() {
return `<false/>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>boolean</string>`;
}
}
exports.BooleanPolicy = BooleanPolicy;
//# sourceMappingURL=booleanPolicy.js.map
+61
View File
@@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BasePolicy } from './basePolicy';
import { CategoryDto, PolicyDto } from './policyDto';
import { renderProfileString } from './render';
import { Category, NlsString, PolicyType, LanguageTranslations } from './types';
export class BooleanPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): BooleanPolicy | undefined {
const { name, minimumVersion, localization, type } = policy;
if (type !== 'boolean') {
return undefined;
}
return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<boolean id="${this.name}" valueName="${this.name}">`,
` <trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>`,
`</boolean>`
];
}
renderADMLPresentationContents() {
return `<checkBox refId="${this.name}">${this.name}</checkBox>`;
}
renderProfileValue(): string {
return `<false/>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>boolean</string>`;
}
}
+53
View File
@@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NumberPolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const basePolicy_1 = require("./basePolicy");
const render_1 = require("./render");
const types_1 = require("./types");
class NumberPolicy extends basePolicy_1.BasePolicy {
defaultValue;
static from(category, policy) {
const { type, default: defaultValue, name, minimumVersion, localization } = policy;
if (type !== 'number') {
return undefined;
}
if (typeof defaultValue !== 'number') {
throw new Error(`Missing required 'default' property.`);
}
return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue);
}
constructor(name, category, minimumVersion, description, moduleName, defaultValue) {
super(types_1.PolicyType.Number, name, category, minimumVersion, description, moduleName);
this.defaultValue = defaultValue;
}
renderADMXElements() {
return [
`<decimal id="${this.name}" valueName="${this.name}" />`
// `<decimal id="Quarantine_PurgeItemsAfterDelay" valueName="PurgeItemsAfterDelay" minValue="0" maxValue="10000000" />`
];
}
renderADMLPresentationContents() {
return `<decimalTextBox refId="${this.name}" defaultValue="${this.defaultValue}">${this.name}</decimalTextBox>`;
}
renderProfileValue() {
return `<integer>${this.defaultValue}</integer>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<integer>${this.defaultValue}</integer>
<key>pfm_description</key>
<string>${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>integer</string>`;
}
}
exports.NumberPolicy = NumberPolicy;
//# sourceMappingURL=numberPolicy.js.map
+65
View File
@@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BasePolicy } from './basePolicy';
import { CategoryDto, PolicyDto } from './policyDto';
import { renderProfileString } from './render';
import { Category, NlsString, PolicyType, LanguageTranslations } from './types';
export class NumberPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): NumberPolicy | undefined {
const { type, default: defaultValue, name, minimumVersion, localization } = policy;
if (type !== 'number') {
return undefined;
}
if (typeof defaultValue !== 'number') {
throw new Error(`Missing required 'default' property.`);
}
return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue);
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
protected readonly defaultValue: number,
) {
super(PolicyType.Number, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<decimal id="${this.name}" valueName="${this.name}" />`
// `<decimal id="Quarantine_PurgeItemsAfterDelay" valueName="PurgeItemsAfterDelay" minValue="0" maxValue="10000000" />`
];
}
renderADMLPresentationContents() {
return `<decimalTextBox refId="${this.name}" defaultValue="${this.defaultValue}">${this.name}</decimalTextBox>`;
}
renderProfileValue() {
return `<integer>${this.defaultValue}</integer>`;
}
renderProfileManifestValue(translations?: LanguageTranslations) {
return `<key>pfm_default</key>
<integer>${this.defaultValue}</integer>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>integer</string>`;
}
}
+46
View File
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObjectPolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const basePolicy_1 = require("./basePolicy");
const render_1 = require("./render");
const types_1 = require("./types");
class ObjectPolicy extends basePolicy_1.BasePolicy {
static from(category, policy) {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'object' && type !== 'array') {
return undefined;
}
return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(types_1.PolicyType.Object, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [`<multiText id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<multiTextBox refId="${this.name}" />`;
}
renderProfileValue() {
return `<string></string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
`;
}
}
exports.ObjectPolicy = ObjectPolicy;
//# sourceMappingURL=objectPolicy.js.map
+58
View File
@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BasePolicy } from './basePolicy';
import { CategoryDto, PolicyDto } from './policyDto';
import { renderProfileString } from './render';
import { Category, NlsString, PolicyType, LanguageTranslations } from './types';
export class ObjectPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): ObjectPolicy | undefined {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'object' && type !== 'array') {
return undefined;
}
return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.Object, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [`<multiText id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<multiTextBox refId="${this.name}" />`;
}
renderProfileValue(): string {
return `<string></string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
`;
}
}
+17 -545
View File
@@ -44,543 +44,15 @@ const minimist_1 = __importDefault(require("minimist"));
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const JSONC = __importStar(require("jsonc-parser"));
const booleanPolicy_1 = require("./booleanPolicy");
const numberPolicy_1 = require("./numberPolicy");
const objectPolicy_1 = require("./objectPolicy");
const stringEnumPolicy_1 = require("./stringEnumPolicy");
const stringPolicy_1 = require("./stringPolicy");
const types_1 = require("./types");
const render_1 = require("./render");
const product = require('../../../product.json');
const packageJson = require('../../../package.json');
var PolicyType;
(function (PolicyType) {
PolicyType["Boolean"] = "boolean";
PolicyType["Number"] = "number";
PolicyType["Object"] = "object";
PolicyType["String"] = "string";
PolicyType["StringEnum"] = "stringEnum";
})(PolicyType || (PolicyType = {}));
function renderADMLString(prefix, moduleName, nlsString, translations) {
let value;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return `<string id="${prefix}_${nlsString.nlsKey.replace(/\./g, '_')}">${value}</string>`;
}
function renderProfileString(_prefix, moduleName, nlsString, translations) {
let value;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return value;
}
class BasePolicy {
type;
name;
category;
minimumVersion;
description;
moduleName;
constructor(type, name, category, minimumVersion, description, moduleName) {
this.type = type;
this.name = name;
this.category = category;
this.minimumVersion = minimumVersion;
this.description = description;
this.moduleName = moduleName;
}
renderADMLString(nlsString, translations) {
return renderADMLString(this.name, this.moduleName, nlsString, translations);
}
renderADMX(regKey) {
return [
`<policy name="${this.name}" class="Both" displayName="$(string.${this.name})" explainText="$(string.${this.name}_${this.description.nlsKey.replace(/\./g, '_')})" key="Software\\Policies\\Microsoft\\${regKey}" presentation="$(presentation.${this.name})">`,
` <parentCategory ref="${this.category.name.nlsKey}" />`,
` <supportedOn ref="Supported_${this.minimumVersion.replace(/\./g, '_')}" />`,
` <elements>`,
...this.renderADMXElements(),
` </elements>`,
`</policy>`
];
}
renderADMLStrings(translations) {
return [
`<string id="${this.name}">${this.name}</string>`,
this.renderADMLString(this.description, translations)
];
}
renderADMLPresentation() {
return `<presentation id="${this.name}">${this.renderADMLPresentationContents()}</presentation>`;
}
renderProfile() {
return [`<key>${this.name}</key>`, this.renderProfileValue()];
}
renderProfileManifest(translations) {
return `<dict>
${this.renderProfileManifestValue(translations)}
</dict>`;
}
}
class BooleanPolicy extends BasePolicy {
static from(category, policy) {
const { name, minimumVersion, localization, type } = policy;
if (type !== 'boolean') {
return undefined;
}
return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [
`<boolean id="${this.name}" valueName="${this.name}">`,
` <trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>`,
`</boolean>`
];
}
renderADMLPresentationContents() {
return `<checkBox refId="${this.name}">${this.name}</checkBox>`;
}
renderProfileValue() {
return `<false/>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>boolean</string>`;
}
}
class NumberPolicy extends BasePolicy {
defaultValue;
static from(category, policy) {
const { type, default: defaultValue, name, minimumVersion, localization } = policy;
if (type !== 'number') {
return undefined;
}
if (typeof defaultValue !== 'number') {
throw new Error(`Missing required 'default' property.`);
}
return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue);
}
constructor(name, category, minimumVersion, description, moduleName, defaultValue) {
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
this.defaultValue = defaultValue;
}
renderADMXElements() {
return [
`<decimal id="${this.name}" valueName="${this.name}" />`
// `<decimal id="Quarantine_PurgeItemsAfterDelay" valueName="PurgeItemsAfterDelay" minValue="0" maxValue="10000000" />`
];
}
renderADMLPresentationContents() {
return `<decimalTextBox refId="${this.name}" defaultValue="${this.defaultValue}">${this.name}</decimalTextBox>`;
}
renderProfileValue() {
return `<integer>${this.defaultValue}</integer>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<integer>${this.defaultValue}</integer>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>integer</string>`;
}
}
class StringPolicy extends BasePolicy {
static from(category, policy) {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'string') {
return undefined;
}
return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(PolicyType.String, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [`<text id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<textBox refId="${this.name}"><label>${this.name}:</label></textBox>`;
}
renderProfileValue() {
return `<string></string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>`;
}
}
class ObjectPolicy extends BasePolicy {
static from(category, policy) {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'object' && type !== 'array') {
return undefined;
}
return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(PolicyType.Object, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [`<multiText id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<multiTextBox refId="${this.name}" />`;
}
renderProfileValue() {
return `<string></string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
`;
}
}
class StringEnumPolicy extends BasePolicy {
enum_;
enumDescriptions;
static from(category, policy) {
const { type, name, minimumVersion, enum: enumValue, localization } = policy;
if (type !== 'string') {
return undefined;
}
const enum_ = enumValue;
if (!enum_) {
return undefined;
}
if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) {
throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`);
}
const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value }));
return new StringEnumPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', enum_, enumDescriptions);
}
constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) {
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
this.enum_ = enum_;
this.enumDescriptions = enumDescriptions;
}
renderADMXElements() {
return [
`<enum id="${this.name}" valueName="${this.name}">`,
...this.enum_.map((value, index) => ` <item displayName="$(string.${this.name}_${this.enumDescriptions[index].nlsKey})"><value><string>${value}</string></value></item>`),
`</enum>`
];
}
renderADMLStrings(translations) {
return [
...super.renderADMLStrings(translations),
...this.enumDescriptions.map(e => this.renderADMLString(e, translations))
];
}
renderADMLPresentationContents() {
return `<dropdownList refId="${this.name}" />`;
}
renderProfileValue() {
return `<string>${this.enum_[0]}</string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string>${this.enum_[0]}</string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
${this.enum_.map(e => `<string>${e}</string>`).join('\n ')}
</array>`;
}
}
function renderADMX(regKey, versions, categories, policies) {
versions = versions.map(v => v.replace(/\./g, '_'));
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.1" schemaVersion="1.0">
<policyNamespaces>
<target prefix="${regKey}" namespace="Microsoft.Policies.${regKey}" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
${versions.map(v => `<definition name="Supported_${v}" displayName="$(string.Supported_${v})" />`).join(`\n `)}
</definitions>
</supportedOn>
<categories>
<category displayName="$(string.Application)" name="Application" />
${categories.map(c => `<category displayName="$(string.Category_${c.name.nlsKey})" name="${c.name.nlsKey}"><parentCategory ref="Application" /></category>`).join(`\n `)}
</categories>
<policies>
${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)}
</policies>
</policyDefinitions>
`;
}
function renderADML(appName, versions, categories, policies, translations) {
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">${appName}</string>
${versions.map(v => `<string id="Supported_${v.replace(/\./g, '_')}">${appName} &gt;= ${v}</string>`).join(`\n `)}
${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)}
${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)}
</stringTable>
<presentationTable>
${policies.map(p => p.renderADMLPresentation()).join(`\n `)}
</presentationTable>
</resources>
</policyDefinitionResources>
`;
}
function renderProfileManifest(appName, bundleIdentifier, _versions, _categories, policies, translations) {
const requiredPayloadFields = `
<dict>
<key>pfm_default</key>
<string>Configure ${appName}</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${appName}</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>`;
const profileManifestSubkeys = policies.map(policy => {
return policy.renderProfileManifest(translations);
}).join('');
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>${appName} Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>${bundleIdentifier}</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
${requiredPayloadFields}
${profileManifestSubkeys}
</array>
<key>pfm_title</key>
<string>${appName}</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>`;
}
function renderMacOSPolicy(policies, translations) {
const appName = product.nameLong;
const bundleIdentifier = product.darwinBundleIdentifier;
const payloadUUID = product.darwinProfilePayloadUUID;
const UUID = product.darwinProfileUUID;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...new Set(policies.map(p => p.category))];
const policyEntries = policies.map(policy => policy.renderProfile())
.flat()
.map(entry => `\t\t\t\t${entry}`)
.join('\n');
return {
profile: `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}.${UUID}</string>
<key>PayloadType</key>
<string>${bundleIdentifier}</string>
<key>PayloadUUID</key>
<string>${UUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
${policyEntries}
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>${payloadUUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`,
manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) }))
]
};
}
function renderGP(policies, translations) {
const appName = product.nameLong;
const regKey = product.win32RegValueName;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))];
return {
admx: renderADMX(regKey, versions, categories, policies),
adml: [
{ languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) }))
]
};
}
const Languages = {
'fr': 'fr-fr',
'it': 'it-it',
'de': 'de-de',
'es': 'es-es',
'ru': 'ru-ru',
'zh-hans': 'zh-cn',
'zh-hant': 'zh-tw',
'ja': 'ja-jp',
'ko': 'ko-kr',
'cs': 'cs-cz',
'pt-br': 'pt-br',
'tr': 'tr-tr',
'pl': 'pl-pl',
};
async function getSpecificNLS(resourceUrlTemplate, languageId, version) {
const resource = {
publisher: 'ms-ceintl',
@@ -648,11 +120,11 @@ async function getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageI
}
// TODO: add more policy types
const PolicyTypes = [
BooleanPolicy,
NumberPolicy,
StringEnumPolicy,
StringPolicy,
ObjectPolicy
booleanPolicy_1.BooleanPolicy,
numberPolicy_1.NumberPolicy,
stringEnumPolicy_1.StringEnumPolicy,
stringPolicy_1.StringPolicy,
objectPolicy_1.ObjectPolicy
];
async function parsePolicies(policyDataFile) {
const contents = JSONC.parse(await fs_1.promises.readFile(policyDataFile, { encoding: 'utf8' }));
@@ -699,18 +171,18 @@ async function getTranslations() {
return [];
}
const version = parseVersion(packageJson.version);
const languageIds = Object.keys(Languages);
const languageIds = Object.keys(types_1.Languages);
return await Promise.all(languageIds.map(languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version)
.then(languageTranslations => ({ languageId, languageTranslations }))));
}
async function windowsMain(policies, translations) {
const root = '.build/policies/win32';
const { admx, adml } = await renderGP(policies, translations);
const { admx, adml } = (0, render_1.renderGP)(product, policies, translations);
await fs_1.promises.rm(root, { recursive: true, force: true });
await fs_1.promises.mkdir(root, { recursive: true });
await fs_1.promises.writeFile(path_1.default.join(root, `${product.win32RegValueName}.admx`), admx.replace(/\r?\n/g, '\n'));
for (const { languageId, contents } of adml) {
const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId]);
const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : types_1.Languages[languageId]);
await fs_1.promises.mkdir(languagePath, { recursive: true });
await fs_1.promises.writeFile(path_1.default.join(languagePath, `${product.win32RegValueName}.adml`), contents.replace(/\r?\n/g, '\n'));
}
@@ -721,12 +193,12 @@ async function darwinMain(policies, translations) {
throw new Error(`Missing required product information.`);
}
const root = '.build/policies/darwin';
const { profile, manifests } = await renderMacOSPolicy(policies, translations);
const { profile, manifests } = (0, render_1.renderMacOSPolicy)(product, policies, translations);
await fs_1.promises.rm(root, { recursive: true, force: true });
await fs_1.promises.mkdir(root, { recursive: true });
await fs_1.promises.writeFile(path_1.default.join(root, `${bundleIdentifier}.mobileconfig`), profile.replace(/\r?\n/g, '\n'));
for (const { languageId, contents } of manifests) {
const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId]);
const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : types_1.Languages[languageId]);
await fs_1.promises.mkdir(languagePath, { recursive: true });
await fs_1.promises.writeFile(path_1.default.join(languagePath, `${bundleIdentifier}.plist`), contents.replace(/\r?\n/g, '\n'));
}
+11 -685
View File
@@ -6,693 +6,19 @@
import minimist from 'minimist';
import { promises as fs } from 'fs';
import path from 'path';
import { CategoryDto, ExportedPolicyDataDto, PolicyDto } from './policyDto';
import { CategoryDto, ExportedPolicyDataDto } from './policyDto';
import * as JSONC from 'jsonc-parser';
import { BooleanPolicy } from './booleanPolicy';
import { NumberPolicy } from './numberPolicy';
import { ObjectPolicy } from './objectPolicy';
import { StringEnumPolicy } from './stringEnumPolicy';
import { StringPolicy } from './stringPolicy';
import { Version, LanguageTranslations, Policy, Translations, Languages, ProductJson } from './types';
import { renderGP, renderMacOSPolicy } from './render';
const product = require('../../../product.json');
const product = require('../../../product.json') as ProductJson;
const packageJson = require('../../../package.json');
type NlsString = { value: string; nlsKey: string };
interface Category {
readonly moduleName: string;
readonly name: NlsString;
}
enum PolicyType {
Boolean = 'boolean',
Number = 'number',
Object = 'object',
String = 'string',
StringEnum = 'stringEnum',
}
interface Policy {
readonly name: string;
readonly type: PolicyType;
readonly category: Category;
readonly minimumVersion: string;
renderADMX(regKey: string): string[];
renderADMLStrings(translations?: LanguageTranslations): string[];
renderADMLPresentation(): string;
renderProfile(): string[];
// https://github.com/ProfileManifests/ProfileManifests/wiki/Manifest-Format
renderProfileManifest(translations?: LanguageTranslations): string;
}
function renderADMLString(prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string {
let value: string | undefined;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return `<string id="${prefix}_${nlsString.nlsKey.replace(/\./g, '_')}">${value}</string>`;
}
function renderProfileString(_prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string {
let value: string | undefined;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return value;
}
abstract class BasePolicy implements Policy {
constructor(
readonly type: PolicyType,
readonly name: string,
readonly category: Category,
readonly minimumVersion: string,
protected description: NlsString,
protected moduleName: string,
) { }
protected renderADMLString(nlsString: NlsString, translations?: LanguageTranslations): string {
return renderADMLString(this.name, this.moduleName, nlsString, translations);
}
renderADMX(regKey: string) {
return [
`<policy name="${this.name}" class="Both" displayName="$(string.${this.name})" explainText="$(string.${this.name}_${this.description.nlsKey.replace(/\./g, '_')})" key="Software\\Policies\\Microsoft\\${regKey}" presentation="$(presentation.${this.name})">`,
` <parentCategory ref="${this.category.name.nlsKey}" />`,
` <supportedOn ref="Supported_${this.minimumVersion.replace(/\./g, '_')}" />`,
` <elements>`,
...this.renderADMXElements(),
` </elements>`,
`</policy>`
];
}
protected abstract renderADMXElements(): string[];
renderADMLStrings(translations?: LanguageTranslations) {
return [
`<string id="${this.name}">${this.name}</string>`,
this.renderADMLString(this.description, translations)
];
}
renderADMLPresentation(): string {
return `<presentation id="${this.name}">${this.renderADMLPresentationContents()}</presentation>`;
}
protected abstract renderADMLPresentationContents(): string;
renderProfile() {
return [`<key>${this.name}</key>`, this.renderProfileValue()];
}
renderProfileManifest(translations?: LanguageTranslations): string {
return `<dict>
${this.renderProfileManifestValue(translations)}
</dict>`;
}
abstract renderProfileValue(): string;
abstract renderProfileManifestValue(translations?: LanguageTranslations): string;
}
class BooleanPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): BooleanPolicy | undefined {
const { name, minimumVersion, localization, type } = policy;
if (type !== 'boolean') {
return undefined;
}
return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<boolean id="${this.name}" valueName="${this.name}">`,
` <trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>`,
`</boolean>`
];
}
renderADMLPresentationContents() {
return `<checkBox refId="${this.name}">${this.name}</checkBox>`;
}
renderProfileValue(): string {
return `<false/>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>boolean</string>`;
}
}
class NumberPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): NumberPolicy | undefined {
const { type, default: defaultValue, name, minimumVersion, localization } = policy;
if (type !== 'number') {
return undefined;
}
if (typeof defaultValue !== 'number') {
throw new Error(`Missing required 'default' property.`);
}
return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue);
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
protected readonly defaultValue: number,
) {
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<decimal id="${this.name}" valueName="${this.name}" />`
// `<decimal id="Quarantine_PurgeItemsAfterDelay" valueName="PurgeItemsAfterDelay" minValue="0" maxValue="10000000" />`
];
}
renderADMLPresentationContents() {
return `<decimalTextBox refId="${this.name}" defaultValue="${this.defaultValue}">${this.name}</decimalTextBox>`;
}
renderProfileValue() {
return `<integer>${this.defaultValue}</integer>`;
}
renderProfileManifestValue(translations?: LanguageTranslations) {
return `<key>pfm_default</key>
<integer>${this.defaultValue}</integer>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>integer</string>`;
}
}
class StringPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): StringPolicy | undefined {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'string') {
return undefined;
}
return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.String, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [`<text id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<textBox refId="${this.name}"><label>${this.name}:</label></textBox>`;
}
renderProfileValue(): string {
return `<string></string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>`;
}
}
class ObjectPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): ObjectPolicy | undefined {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'object' && type !== 'array') {
return undefined;
}
return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.Object, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [`<multiText id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<multiTextBox refId="${this.name}" />`;
}
renderProfileValue(): string {
return `<string></string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
`;
}
}
class StringEnumPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): StringEnumPolicy | undefined {
const { type, name, minimumVersion, enum: enumValue, localization } = policy;
if (type !== 'string') {
return undefined;
}
const enum_ = enumValue;
if (!enum_) {
return undefined;
}
if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) {
throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`);
}
const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value }));
return new StringEnumPolicy(
name,
{ moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } },
minimumVersion,
{ nlsKey: localization.description.key, value: localization.description.value },
'',
enum_,
enumDescriptions
);
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
protected enum_: string[],
protected enumDescriptions: NlsString[],
) {
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<enum id="${this.name}" valueName="${this.name}">`,
...this.enum_.map((value, index) => ` <item displayName="$(string.${this.name}_${this.enumDescriptions[index].nlsKey})"><value><string>${value}</string></value></item>`),
`</enum>`
];
}
renderADMLStrings(translations?: LanguageTranslations) {
return [
...super.renderADMLStrings(translations),
...this.enumDescriptions.map(e => this.renderADMLString(e, translations))
];
}
renderADMLPresentationContents() {
return `<dropdownList refId="${this.name}" />`;
}
renderProfileValue() {
return `<string>${this.enum_[0]}</string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string>${this.enum_[0]}</string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
${this.enum_.map(e => `<string>${e}</string>`).join('\n ')}
</array>`;
}
}
function renderADMX(regKey: string, versions: string[], categories: Category[], policies: Policy[]) {
versions = versions.map(v => v.replace(/\./g, '_'));
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.1" schemaVersion="1.0">
<policyNamespaces>
<target prefix="${regKey}" namespace="Microsoft.Policies.${regKey}" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
${versions.map(v => `<definition name="Supported_${v}" displayName="$(string.Supported_${v})" />`).join(`\n `)}
</definitions>
</supportedOn>
<categories>
<category displayName="$(string.Application)" name="Application" />
${categories.map(c => `<category displayName="$(string.Category_${c.name.nlsKey})" name="${c.name.nlsKey}"><parentCategory ref="Application" /></category>`).join(`\n `)}
</categories>
<policies>
${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)}
</policies>
</policyDefinitions>
`;
}
function renderADML(appName: string, versions: string[], categories: Category[], policies: Policy[], translations?: LanguageTranslations) {
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">${appName}</string>
${versions.map(v => `<string id="Supported_${v.replace(/\./g, '_')}">${appName} &gt;= ${v}</string>`).join(`\n `)}
${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)}
${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)}
</stringTable>
<presentationTable>
${policies.map(p => p.renderADMLPresentation()).join(`\n `)}
</presentationTable>
</resources>
</policyDefinitionResources>
`;
}
function renderProfileManifest(appName: string, bundleIdentifier: string, _versions: string[], _categories: Category[], policies: Policy[], translations?: LanguageTranslations) {
const requiredPayloadFields = `
<dict>
<key>pfm_default</key>
<string>Configure ${appName}</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${appName}</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>`;
const profileManifestSubkeys = policies.map(policy => {
return policy.renderProfileManifest(translations);
}).join('');
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>${appName} Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>${bundleIdentifier}</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
${requiredPayloadFields}
${profileManifestSubkeys}
</array>
<key>pfm_title</key>
<string>${appName}</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>`;
}
function renderMacOSPolicy(policies: Policy[], translations: Translations) {
const appName = product.nameLong;
const bundleIdentifier = product.darwinBundleIdentifier;
const payloadUUID = product.darwinProfilePayloadUUID;
const UUID = product.darwinProfileUUID;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...new Set(policies.map(p => p.category))];
const policyEntries =
policies.map(policy => policy.renderProfile())
.flat()
.map(entry => `\t\t\t\t${entry}`)
.join('\n');
return {
profile: `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}.${UUID}</string>
<key>PayloadType</key>
<string>${bundleIdentifier}</string>
<key>PayloadUUID</key>
<string>${UUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
${policyEntries}
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>${payloadUUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`,
manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) =>
({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) }))
]
};
}
function renderGP(policies: Policy[], translations: Translations) {
const appName = product.nameLong;
const regKey = product.win32RegValueName;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))] as Category[];
return {
admx: renderADMX(regKey, versions, categories, policies),
adml: [
{ languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) =>
({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) }))
]
};
}
const Languages = {
'fr': 'fr-fr',
'it': 'it-it',
'de': 'de-de',
'es': 'es-es',
'ru': 'ru-ru',
'zh-hans': 'zh-cn',
'zh-hant': 'zh-tw',
'ja': 'ja-jp',
'ko': 'ko-kr',
'cs': 'cs-cz',
'pt-br': 'pt-br',
'tr': 'tr-tr',
'pl': 'pl-pl',
};
type LanguageTranslations = { [moduleName: string]: { [nlsKey: string]: string } };
type Translations = { languageId: string; languageTranslations: LanguageTranslations }[];
type Version = [number, number, number];
async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, version: Version): Promise<LanguageTranslations> {
const resource = {
publisher: 'ms-ceintl',
@@ -843,7 +169,7 @@ async function getTranslations(): Promise<Translations> {
async function windowsMain(policies: Policy[], translations: Translations) {
const root = '.build/policies/win32';
const { admx, adml } = await renderGP(policies, translations);
const { admx, adml } = renderGP(product, policies, translations);
await fs.rm(root, { recursive: true, force: true });
await fs.mkdir(root, { recursive: true });
@@ -863,7 +189,7 @@ async function darwinMain(policies: Policy[], translations: Translations) {
throw new Error(`Missing required product information.`);
}
const root = '.build/policies/darwin';
const { profile, manifests } = await renderMacOSPolicy(policies, translations);
const { profile, manifests } = renderMacOSPolicy(product, policies, translations);
await fs.rm(root, { recursive: true, force: true });
await fs.mkdir(root, { recursive: true });
+271
View File
@@ -0,0 +1,271 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderADMLString = renderADMLString;
exports.renderProfileString = renderProfileString;
exports.renderADMX = renderADMX;
exports.renderADML = renderADML;
exports.renderProfileManifest = renderProfileManifest;
exports.renderMacOSPolicy = renderMacOSPolicy;
exports.renderGP = renderGP;
function renderADMLString(prefix, moduleName, nlsString, translations) {
let value;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return `<string id="${prefix}_${nlsString.nlsKey.replace(/\./g, '_')}">${value}</string>`;
}
function renderProfileString(_prefix, moduleName, nlsString, translations) {
let value;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return value;
}
function renderADMX(regKey, versions, categories, policies) {
versions = versions.map(v => v.replace(/\./g, '_'));
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.1" schemaVersion="1.0">
<policyNamespaces>
<target prefix="${regKey}" namespace="Microsoft.Policies.${regKey}" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
${versions.map(v => `<definition name="Supported_${v}" displayName="$(string.Supported_${v})" />`).join(`\n `)}
</definitions>
</supportedOn>
<categories>
<category displayName="$(string.Application)" name="Application" />
${categories.map(c => `<category displayName="$(string.Category_${c.name.nlsKey})" name="${c.name.nlsKey}"><parentCategory ref="Application" /></category>`).join(`\n `)}
</categories>
<policies>
${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)}
</policies>
</policyDefinitions>
`;
}
function renderADML(appName, versions, categories, policies, translations) {
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">${appName}</string>
${versions.map(v => `<string id="Supported_${v.replace(/\./g, '_')}">${appName} &gt;= ${v}</string>`).join(`\n `)}
${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)}
${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)}
</stringTable>
<presentationTable>
${policies.map(p => p.renderADMLPresentation()).join(`\n `)}
</presentationTable>
</resources>
</policyDefinitionResources>
`;
}
function renderProfileManifest(appName, bundleIdentifier, _versions, _categories, policies, translations) {
const requiredPayloadFields = `
<dict>
<key>pfm_default</key>
<string>Configure ${appName}</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${appName}</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>`;
const profileManifestSubkeys = policies.map(policy => {
return policy.renderProfileManifest(translations);
}).join('');
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>${appName} Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>${bundleIdentifier}</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
${requiredPayloadFields}
${profileManifestSubkeys}
</array>
<key>pfm_title</key>
<string>${appName}</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>`;
}
function renderMacOSPolicy(product, policies, translations) {
const appName = product.nameLong;
const bundleIdentifier = product.darwinBundleIdentifier;
const payloadUUID = product.darwinProfilePayloadUUID;
const UUID = product.darwinProfileUUID;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...new Set(policies.map(p => p.category))];
const policyEntries = policies.map(policy => policy.renderProfile())
.flat()
.map(entry => `\t\t\t\t${entry}`)
.join('\n');
return {
profile: `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}.${UUID}</string>
<key>PayloadType</key>
<string>${bundleIdentifier}</string>
<key>PayloadUUID</key>
<string>${UUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
${policyEntries}
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>${payloadUUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`,
manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) }))
]
};
}
function renderGP(product, policies, translations) {
const appName = product.nameLong;
const regKey = product.win32RegValueName;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))];
return {
admx: renderADMX(regKey, versions, categories, policies),
adml: [
{ languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) }))
]
};
}
//# sourceMappingURL=render.js.map
+295
View File
@@ -0,0 +1,295 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NlsString, LanguageTranslations, Category, Policy, Translations, ProductJson } from './types';
export function renderADMLString(prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string {
let value: string | undefined;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return `<string id="${prefix}_${nlsString.nlsKey.replace(/\./g, '_')}">${value}</string>`;
}
export function renderProfileString(_prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string {
let value: string | undefined;
if (translations) {
const moduleTranslations = translations[moduleName];
if (moduleTranslations) {
value = moduleTranslations[nlsString.nlsKey];
}
}
if (!value) {
value = nlsString.value;
}
return value;
}
export function renderADMX(regKey: string, versions: string[], categories: Category[], policies: Policy[]) {
versions = versions.map(v => v.replace(/\./g, '_'));
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.1" schemaVersion="1.0">
<policyNamespaces>
<target prefix="${regKey}" namespace="Microsoft.Policies.${regKey}" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
${versions.map(v => `<definition name="Supported_${v}" displayName="$(string.Supported_${v})" />`).join(`\n `)}
</definitions>
</supportedOn>
<categories>
<category displayName="$(string.Application)" name="Application" />
${categories.map(c => `<category displayName="$(string.Category_${c.name.nlsKey})" name="${c.name.nlsKey}"><parentCategory ref="Application" /></category>`).join(`\n `)}
</categories>
<policies>
${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)}
</policies>
</policyDefinitions>
`;
}
export function renderADML(appName: string, versions: string[], categories: Category[], policies: Policy[], translations?: LanguageTranslations) {
return `<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">${appName}</string>
${versions.map(v => `<string id="Supported_${v.replace(/\./g, '_')}">${appName} &gt;= ${v}</string>`).join(`\n `)}
${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)}
${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)}
</stringTable>
<presentationTable>
${policies.map(p => p.renderADMLPresentation()).join(`\n `)}
</presentationTable>
</resources>
</policyDefinitionResources>
`;
}
export function renderProfileManifest(appName: string, bundleIdentifier: string, _versions: string[], _categories: Category[], policies: Policy[], translations?: LanguageTranslations) {
const requiredPayloadFields = `
<dict>
<key>pfm_default</key>
<string>Configure ${appName}</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${appName}</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>${bundleIdentifier}</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>`;
const profileManifestSubkeys = policies.map(policy => {
return policy.renderProfileManifest(translations);
}).join('');
return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>${appName} Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>${bundleIdentifier}</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
${requiredPayloadFields}
${profileManifestSubkeys}
</array>
<key>pfm_title</key>
<string>${appName}</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>`;
}
export function renderMacOSPolicy(product: ProductJson, policies: Policy[], translations: Translations) {
const appName = product.nameLong;
const bundleIdentifier = product.darwinBundleIdentifier;
const payloadUUID = product.darwinProfilePayloadUUID;
const UUID = product.darwinProfileUUID;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...new Set(policies.map(p => p.category))];
const policyEntries =
policies.map(policy => policy.renderProfile())
.flat()
.map(entry => `\t\t\t\t${entry}`)
.join('\n');
return {
profile: `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}.${UUID}</string>
<key>PayloadType</key>
<string>${bundleIdentifier}</string>
<key>PayloadUUID</key>
<string>${UUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
${policyEntries}
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>${appName}</string>
<key>PayloadIdentifier</key>
<string>${bundleIdentifier}</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>${payloadUUID}</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`,
manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) =>
({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) }))
]
};
}
export function renderGP(product: ProductJson, policies: Policy[], translations: Translations) {
const appName = product.nameLong;
const regKey = product.win32RegValueName;
const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort();
const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))] as Category[];
return {
admx: renderADMX(regKey, versions, categories, policies),
adml: [
{ languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) },
...translations.map(({ languageId, languageTranslations }) =>
({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) }))
]
};
}
+71
View File
@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StringEnumPolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const basePolicy_1 = require("./basePolicy");
const render_1 = require("./render");
const types_1 = require("./types");
class StringEnumPolicy extends basePolicy_1.BasePolicy {
enum_;
enumDescriptions;
static from(category, policy) {
const { type, name, minimumVersion, enum: enumValue, localization } = policy;
if (type !== 'string') {
return undefined;
}
const enum_ = enumValue;
if (!enum_) {
return undefined;
}
if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) {
throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`);
}
const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value }));
return new StringEnumPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', enum_, enumDescriptions);
}
constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) {
super(types_1.PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
this.enum_ = enum_;
this.enumDescriptions = enumDescriptions;
}
renderADMXElements() {
return [
`<enum id="${this.name}" valueName="${this.name}">`,
...this.enum_.map((value, index) => ` <item displayName="$(string.${this.name}_${this.enumDescriptions[index].nlsKey})"><value><string>${value}</string></value></item>`),
`</enum>`
];
}
renderADMLStrings(translations) {
return [
...super.renderADMLStrings(translations),
...this.enumDescriptions.map(e => this.renderADMLString(e, translations))
];
}
renderADMLPresentationContents() {
return `<dropdownList refId="${this.name}" />`;
}
renderProfileValue() {
return `<string>${this.enum_[0]}</string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string>${this.enum_[0]}</string>
<key>pfm_description</key>
<string>${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
${this.enum_.map(e => `<string>${e}</string>`).join('\n ')}
</array>`;
}
}
exports.StringEnumPolicy = StringEnumPolicy;
//# sourceMappingURL=stringEnumPolicy.js.map
+92
View File
@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BasePolicy } from './basePolicy';
import { CategoryDto, PolicyDto } from './policyDto';
import { renderProfileString } from './render';
import { Category, NlsString, PolicyType, LanguageTranslations } from './types';
export class StringEnumPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): StringEnumPolicy | undefined {
const { type, name, minimumVersion, enum: enumValue, localization } = policy;
if (type !== 'string') {
return undefined;
}
const enum_ = enumValue;
if (!enum_) {
return undefined;
}
if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) {
throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`);
}
const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value }));
return new StringEnumPolicy(
name,
{ moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } },
minimumVersion,
{ nlsKey: localization.description.key, value: localization.description.value },
'',
enum_,
enumDescriptions
);
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
protected enum_: string[],
protected enumDescriptions: NlsString[],
) {
super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [
`<enum id="${this.name}" valueName="${this.name}">`,
...this.enum_.map((value, index) => ` <item displayName="$(string.${this.name}_${this.enumDescriptions[index].nlsKey})"><value><string>${value}</string></value></item>`),
`</enum>`
];
}
renderADMLStrings(translations?: LanguageTranslations) {
return [
...super.renderADMLStrings(translations),
...this.enumDescriptions.map(e => this.renderADMLString(e, translations))
];
}
renderADMLPresentationContents() {
return `<dropdownList refId="${this.name}" />`;
}
renderProfileValue() {
return `<string>${this.enum_[0]}</string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string>${this.enum_[0]}</string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
${this.enum_.map(e => `<string>${e}</string>`).join('\n ')}
</array>`;
}
}
+45
View File
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StringPolicy = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const basePolicy_1 = require("./basePolicy");
const render_1 = require("./render");
const types_1 = require("./types");
class StringPolicy extends basePolicy_1.BasePolicy {
static from(category, policy) {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'string') {
return undefined;
}
return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
constructor(name, category, minimumVersion, description, moduleName) {
super(types_1.PolicyType.String, name, category, minimumVersion, description, moduleName);
}
renderADMXElements() {
return [`<text id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<textBox refId="${this.name}"><label>${this.name}:</label></textBox>`;
}
renderProfileValue() {
return `<string></string>`;
}
renderProfileManifestValue(translations) {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>`;
}
}
exports.StringPolicy = StringPolicy;
//# sourceMappingURL=stringPolicy.js.map
+57
View File
@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BasePolicy } from './basePolicy';
import { CategoryDto, PolicyDto } from './policyDto';
import { renderProfileString } from './render';
import { Category, NlsString, PolicyType, LanguageTranslations } from './types';
export class StringPolicy extends BasePolicy {
static from(category: CategoryDto, policy: PolicyDto): StringPolicy | undefined {
const { type, name, minimumVersion, localization } = policy;
if (type !== 'string') {
return undefined;
}
return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '');
}
private constructor(
name: string,
category: Category,
minimumVersion: string,
description: NlsString,
moduleName: string,
) {
super(PolicyType.String, name, category, minimumVersion, description, moduleName);
}
protected renderADMXElements(): string[] {
return [`<text id="${this.name}" valueName="${this.name}" required="true" />`];
}
renderADMLPresentationContents() {
return `<textBox refId="${this.name}"><label>${this.name}:</label></textBox>`;
}
renderProfileValue(): string {
return `<string></string>`;
}
renderProfileManifestValue(translations?: LanguageTranslations): string {
return `<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>${renderProfileString(this.name, this.moduleName, this.description, translations)}</string>
<key>pfm_name</key>
<string>${this.name}</string>
<key>pfm_title</key>
<string>${this.name}</string>
<key>pfm_type</key>
<string>string</string>`;
}
}
+27
View File
@@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Languages = exports.PolicyType = void 0;
var PolicyType;
(function (PolicyType) {
PolicyType["Boolean"] = "boolean";
PolicyType["Number"] = "number";
PolicyType["Object"] = "object";
PolicyType["String"] = "string";
PolicyType["StringEnum"] = "stringEnum";
})(PolicyType || (exports.PolicyType = PolicyType = {}));
exports.Languages = {
'fr': 'fr-fr',
'it': 'it-it',
'de': 'de-de',
'es': 'es-es',
'ru': 'ru-ru',
'zh-hans': 'zh-cn',
'zh-hant': 'zh-tw',
'ja': 'ja-jp',
'ko': 'ko-kr',
'cs': 'cs-cz',
'pt-br': 'pt-br',
'tr': 'tr-tr',
'pl': 'pl-pl',
};
//# sourceMappingURL=types.js.map
+65
View File
@@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface ProductJson {
readonly nameLong: string;
readonly darwinBundleIdentifier: string;
readonly darwinProfilePayloadUUID: string;
readonly darwinProfileUUID: string;
readonly win32RegValueName: string;
readonly extensionsGallery?: {
readonly serviceUrl: string;
readonly resourceUrlTemplate: string;
};
}
export interface Policy {
readonly name: string;
readonly type: PolicyType;
readonly category: Category;
readonly minimumVersion: string;
renderADMX(regKey: string): string[];
renderADMLStrings(translations?: LanguageTranslations): string[];
renderADMLPresentation(): string;
renderProfile(): string[];
// https://github.com/ProfileManifests/ProfileManifests/wiki/Manifest-Format
renderProfileManifest(translations?: LanguageTranslations): string;
}
export type NlsString = { value: string; nlsKey: string };
export interface Category {
readonly moduleName: string;
readonly name: NlsString;
}
export enum PolicyType {
Boolean = 'boolean',
Number = 'number',
Object = 'object',
String = 'string',
StringEnum = 'stringEnum',
}
export const Languages = {
'fr': 'fr-fr',
'it': 'it-it',
'de': 'de-de',
'es': 'es-es',
'ru': 'ru-ru',
'zh-hans': 'zh-cn',
'zh-hant': 'zh-tw',
'ja': 'ja-jp',
'ko': 'ko-kr',
'cs': 'cs-cz',
'pt-br': 'pt-br',
'tr': 'tr-tr',
'pl': 'pl-pl',
};
export type LanguageTranslations = { [moduleName: string]: { [nlsKey: string]: string } };
export type Translations = { languageId: string; languageTranslations: LanguageTranslations }[];
export type Version = [number, number, number];
+120
View File
@@ -0,0 +1,120 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const booleanPolicy_js_1 = require("../policies/booleanPolicy.js");
const types_js_1 = require("../policies/types.js");
suite('BooleanPolicy', () => {
const mockCategory = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy = {
key: 'test.boolean.policy',
name: 'TestBooleanPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'boolean',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' }
}
};
test('should create BooleanPolicy from factory method', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
assert_1.default.strictEqual(policy.name, 'TestBooleanPolicy');
assert_1.default.strictEqual(policy.minimumVersion, '1.0');
assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value);
assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Boolean);
});
test('should render ADMX elements correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admx = policy.renderADMX('TestKey');
assert_1.default.deepStrictEqual(admx, [
'<policy name="TestBooleanPolicy" class="Both" displayName="$(string.TestBooleanPolicy)" explainText="$(string.TestBooleanPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestBooleanPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<boolean id="TestBooleanPolicy" valueName="TestBooleanPolicy">',
'\t<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>',
'</boolean>',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestBooleanPolicy">TestBooleanPolicy</string>',
'<string id="TestBooleanPolicy_test_policy_description">Test policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestBooleanPolicy">TestBooleanPolicy</string>',
'<string id="TestBooleanPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const presentation = policy.renderADMLPresentation();
assert_1.default.strictEqual(presentation, '<presentation id="TestBooleanPolicy"><checkBox refId="TestBooleanPolicy">TestBooleanPolicy</checkBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profileValue = policy.renderProfileValue();
assert_1.default.strictEqual(profileValue, '<false/>');
});
test('should render profile correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profile = policy.renderProfile();
assert_1.default.strictEqual(profile.length, 2);
assert_1.default.strictEqual(profile[0], '<key>TestBooleanPolicy</key>');
assert_1.default.strictEqual(profile[1], '<false/>');
});
test('should render profile manifest value correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>');
});
test('should render profile manifest value with translations', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>');
});
test('should render profile manifest correctly', () => {
const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifest = policy.renderProfileManifest();
assert_1.default.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>\n</dict>');
});
});
//# sourceMappingURL=booleanPolicy.test.js.map
+158
View File
@@ -0,0 +1,158 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { BooleanPolicy } from '../policies/booleanPolicy.js';
import { LanguageTranslations, PolicyType } from '../policies/types.js';
import { CategoryDto, PolicyDto } from '../policies/policyDto.js';
suite('BooleanPolicy', () => {
const mockCategory: CategoryDto = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy: PolicyDto = {
key: 'test.boolean.policy',
name: 'TestBooleanPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'boolean',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' }
}
};
test('should create BooleanPolicy from factory method', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
assert.strictEqual(policy.name, 'TestBooleanPolicy');
assert.strictEqual(policy.minimumVersion, '1.0');
assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert.strictEqual(policy.category.name.value, mockCategory.name.value);
assert.strictEqual(policy.type, PolicyType.Boolean);
});
test('should render ADMX elements correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admx = policy.renderADMX('TestKey');
assert.deepStrictEqual(admx, [
'<policy name="TestBooleanPolicy" class="Both" displayName="$(string.TestBooleanPolicy)" explainText="$(string.TestBooleanPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestBooleanPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<boolean id="TestBooleanPolicy" valueName="TestBooleanPolicy">',
'\t<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>',
'</boolean>',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert.deepStrictEqual(admlStrings, [
'<string id="TestBooleanPolicy">TestBooleanPolicy</string>',
'<string id="TestBooleanPolicy_test_policy_description">Test policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert.deepStrictEqual(admlStrings, [
'<string id="TestBooleanPolicy">TestBooleanPolicy</string>',
'<string id="TestBooleanPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const presentation = policy.renderADMLPresentation();
assert.strictEqual(presentation, '<presentation id="TestBooleanPolicy"><checkBox refId="TestBooleanPolicy">TestBooleanPolicy</checkBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profileValue = policy.renderProfileValue();
assert.strictEqual(profileValue, '<false/>');
});
test('should render profile correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profile = policy.renderProfile();
assert.strictEqual(profile.length, 2);
assert.strictEqual(profile[0], '<key>TestBooleanPolicy</key>');
assert.strictEqual(profile[1], '<false/>');
});
test('should render profile manifest value correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>');
});
test('should render profile manifest value with translations', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>');
});
test('should render profile manifest correctly', () => {
const policy = BooleanPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifest = policy.renderProfileManifest();
assert.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<false/>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_title</key>\n<string>TestBooleanPolicy</string>\n<key>pfm_type</key>\n<string>boolean</string>\n</dict>');
});
});
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>Code - OSS</string>
<key>PayloadIdentifier</key>
<string>com.visualstudio.code.oss.47827DD9-4734-49A0-AF80-7E19B11495CC</string>
<key>PayloadType</key>
<string>com.visualstudio.code.oss</string>
<key>PayloadUUID</key>
<string>47827DD9-4734-49A0-AF80-7E19B11495CC</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>ChatAgentExtensionTools</key>
<false/>
<key>ChatAgentMode</key>
<false/>
<key>ChatMCP</key>
<string>none</string>
<key>ChatPromptFiles</key>
<false/>
<key>ChatToolsAutoApprove</key>
<false/>
<key>McpGalleryServiceUrl</key>
<string></string>
<key>AllowedExtensions</key>
<string></string>
<key>ExtensionGalleryServiceUrl</key>
<string></string>
<key>ChatToolsTerminalEnableAutoApprove</key>
<false/>
<key>EnableFeedback</key>
<false/>
<key>TelemetryLevel</key>
<string>all</string>
<key>UpdateMode</key>
<string>none</string>
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages Code - OSS. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>Code - OSS</string>
<key>PayloadIdentifier</key>
<string>com.visualstudio.code.oss</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>CF808BE7-53F3-46C6-A7E2-7EDB98A5E959</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>
@@ -0,0 +1,274 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>Code - OSS Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>2025-10-21T23:04:34Z</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
<dict>
<key>pfm_default</key>
<string>Configure Code - OSS</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Code - OSS</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Enable using tools contributed by third-party extensions.</string>
<key>pfm_name</key>
<string>ChatAgentExtensionTools</string>
<key>pfm_title</key>
<string>ChatAgentExtensionTools</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.</string>
<key>pfm_name</key>
<string>ChatAgentMode</string>
<key>pfm_title</key>
<string>ChatAgentMode</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string>none</string>
<key>pfm_description</key>
<string>Controls access to installed Model Context Protocol servers.</string>
<key>pfm_name</key>
<string>ChatMCP</string>
<key>pfm_title</key>
<string>ChatMCP</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>none</string>
<string>registry</string>
<string>all</string>
</array>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Enables reusable prompt and instruction files in Chat sessions.</string>
<key>pfm_name</key>
<string>ChatPromptFiles</string>
<key>pfm_title</key>
<string>ChatPromptFiles</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.
This feature disables critical security protections and makes it much easier for an attacker to compromise the machine.</string>
<key>pfm_name</key>
<string>ChatToolsAutoApprove</string>
<key>pfm_title</key>
<string>ChatToolsAutoApprove</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Configure the MCP Gallery service URL to connect to</string>
<key>pfm_name</key>
<string>McpGalleryServiceUrl</string>
<key>pfm_title</key>
<string>McpGalleryServiceUrl</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions</string>
<key>pfm_name</key>
<string>AllowedExtensions</string>
<key>pfm_title</key>
<string>AllowedExtensions</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Configure the Marketplace service URL to connect to</string>
<key>pfm_name</key>
<string>ExtensionGalleryServiceUrl</string>
<key>pfm_title</key>
<string>ExtensionGalleryServiceUrl</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Controls whether to allow auto approval in the run in terminal tool.</string>
<key>pfm_name</key>
<string>ChatToolsTerminalEnableAutoApprove</string>
<key>pfm_title</key>
<string>ChatToolsTerminalEnableAutoApprove</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.</string>
<key>pfm_name</key>
<string>EnableFeedback</string>
<key>pfm_title</key>
<string>EnableFeedback</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string>all</string>
<key>pfm_description</key>
<string>Controls the level of telemetry.</string>
<key>pfm_name</key>
<string>TelemetryLevel</string>
<key>pfm_title</key>
<string>TelemetryLevel</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>all</string>
<string>error</string>
<string>crash</string>
<string>off</string>
</array>
</dict><dict>
<key>pfm_default</key>
<string>none</string>
<key>pfm_description</key>
<string>Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.</string>
<key>pfm_name</key>
<string>UpdateMode</string>
<key>pfm_title</key>
<string>UpdateMode</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>none</string>
<string>manual</string>
<string>start</string>
<string>default</string>
</array>
</dict>
</array>
<key>pfm_title</key>
<string>Code - OSS</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>
@@ -0,0 +1,274 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>pfm_app_url</key>
<string>https://code.visualstudio.com/</string>
<key>pfm_description</key>
<string>Code - OSS Managed Settings</string>
<key>pfm_documentation_url</key>
<string>https://code.visualstudio.com/docs/setup/enterprise</string>
<key>pfm_domain</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_format_version</key>
<integer>1</integer>
<key>pfm_interaction</key>
<string>combined</string>
<key>pfm_last_modified</key>
<date>2025-10-21T23:04:34Z</date>
<key>pfm_platforms</key>
<array>
<string>macOS</string>
</array>
<key>pfm_subkeys</key>
<array>
<dict>
<key>pfm_default</key>
<string>Configure Code - OSS</string>
<key>pfm_name</key>
<string>PayloadDescription</string>
<key>pfm_title</key>
<string>Payload Description</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Code - OSS</string>
<key>pfm_name</key>
<string>PayloadDisplayName</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Display Name</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_name</key>
<string>PayloadIdentifier</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Identifier</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string>com.visualstudio.code.oss</string>
<key>pfm_name</key>
<string>PayloadType</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Type</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<string></string>
<key>pfm_name</key>
<string>PayloadUUID</string>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload UUID</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<integer>1</integer>
<key>pfm_name</key>
<string>PayloadVersion</string>
<key>pfm_range_list</key>
<array>
<integer>1</integer>
</array>
<key>pfm_require</key>
<string>always</string>
<key>pfm_title</key>
<string>Payload Version</string>
<key>pfm_type</key>
<string>integer</string>
</dict>
<dict>
<key>pfm_default</key>
<string>Microsoft</string>
<key>pfm_name</key>
<string>PayloadOrganization</string>
<key>pfm_title</key>
<string>Payload Organization</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Autorisez lutilisation doutils fournis par des extensions tierces.</string>
<key>pfm_name</key>
<string>ChatAgentExtensionTools</string>
<key>pfm_title</key>
<string>ChatAgentExtensionTools</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.</string>
<key>pfm_name</key>
<string>ChatAgentMode</string>
<key>pfm_title</key>
<string>ChatAgentMode</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string>none</string>
<key>pfm_description</key>
<string>Contrôle laccès aux serveurs de protocole de contexte du modèle.</string>
<key>pfm_name</key>
<string>ChatMCP</string>
<key>pfm_title</key>
<string>ChatMCP</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>none</string>
<string>registry</string>
<string>all</string>
</array>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Active les fichiers dinstruction et de requête réutilisables dans les sessions Conversation.</string>
<key>pfm_name</key>
<string>ChatPromptFiles</string>
<key>pfm_title</key>
<string>ChatPromptFiles</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Lapprobation automatique globale, également appelée « mode YOLO », désactive complètement lapprobation manuelle pour tous les outils dans tous les espaces de travail, permettant à lagent dagir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises.
Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.</string>
<key>pfm_name</key>
<string>ChatToolsAutoApprove</string>
<key>pfm_title</key>
<string>ChatToolsAutoApprove</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Configurer lURL du service de la galerie MCP à laquelle se connecter</string>
<key>pfm_name</key>
<string>McpGalleryServiceUrl</string>
<key>pfm_title</key>
<string>McpGalleryServiceUrl</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Spécifiez une liste dextensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant lutilisation dextensions non autorisées. Plus dinformations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions</string>
<key>pfm_name</key>
<string>AllowedExtensions</string>
<key>pfm_title</key>
<string>AllowedExtensions</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<string></string>
<key>pfm_description</key>
<string>Configurer lURL du service Place de marché à laquelle se connecter</string>
<key>pfm_name</key>
<string>ExtensionGalleryServiceUrl</string>
<key>pfm_title</key>
<string>ExtensionGalleryServiceUrl</string>
<key>pfm_type</key>
<string>string</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Contrôle sil faut autoriser lapprobation automatique lors de lexécution dans loutil terminal.</string>
<key>pfm_name</key>
<string>ChatToolsTerminalEnableAutoApprove</string>
<key>pfm_title</key>
<string>ChatToolsTerminalEnableAutoApprove</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.</string>
<key>pfm_name</key>
<string>EnableFeedback</string>
<key>pfm_title</key>
<string>EnableFeedback</string>
<key>pfm_type</key>
<string>boolean</string>
</dict><dict>
<key>pfm_default</key>
<string>all</string>
<key>pfm_description</key>
<string>Contrôle le niveau de télémétrie.</string>
<key>pfm_name</key>
<string>TelemetryLevel</string>
<key>pfm_title</key>
<string>TelemetryLevel</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>all</string>
<string>error</string>
<string>crash</string>
<string>off</string>
</array>
</dict><dict>
<key>pfm_default</key>
<string>none</string>
<key>pfm_description</key>
<string>Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.</string>
<key>pfm_name</key>
<string>UpdateMode</string>
<key>pfm_title</key>
<string>UpdateMode</string>
<key>pfm_type</key>
<string>string</string>
<key>pfm_range_list</key>
<array>
<string>none</string>
<string>manual</string>
<string>start</string>
<string>default</string>
</array>
</dict>
</array>
<key>pfm_title</key>
<string>Code - OSS</string>
<key>pfm_unique</key>
<true/>
<key>pfm_version</key>
<integer>1</integer>
</dict>
</plist>
+136
View File
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.1" schemaVersion="1.0">
<policyNamespaces>
<target prefix="CodeOSS" namespace="Microsoft.Policies.CodeOSS" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
<definition name="Supported_1_101" displayName="$(string.Supported_1_101)" />
<definition name="Supported_1_104" displayName="$(string.Supported_1_104)" />
<definition name="Supported_1_67" displayName="$(string.Supported_1_67)" />
<definition name="Supported_1_96" displayName="$(string.Supported_1_96)" />
<definition name="Supported_1_99" displayName="$(string.Supported_1_99)" />
</definitions>
</supportedOn>
<categories>
<category displayName="$(string.Application)" name="Application" />
<category displayName="$(string.Category_interactiveSessionConfigurationTitle)" name="interactiveSessionConfigurationTitle"><parentCategory ref="Application" /></category>
<category displayName="$(string.Category_extensionsConfigurationTitle)" name="extensionsConfigurationTitle"><parentCategory ref="Application" /></category>
<category displayName="$(string.Category_terminalIntegratedConfigurationTitle)" name="terminalIntegratedConfigurationTitle"><parentCategory ref="Application" /></category>
<category displayName="$(string.Category_telemetryConfigurationTitle)" name="telemetryConfigurationTitle"><parentCategory ref="Application" /></category>
<category displayName="$(string.Category_updateConfigurationTitle)" name="updateConfigurationTitle"><parentCategory ref="Application" /></category>
</categories>
<policies>
<policy name="ChatAgentExtensionTools" class="Both" displayName="$(string.ChatAgentExtensionTools)" explainText="$(string.ChatAgentExtensionTools_chat_extensionToolsEnabled)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatAgentExtensionTools)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<boolean id="ChatAgentExtensionTools" valueName="ChatAgentExtensionTools">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="ChatAgentMode" class="Both" displayName="$(string.ChatAgentMode)" explainText="$(string.ChatAgentMode_chat_agent_enabled_description)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatAgentMode)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<boolean id="ChatAgentMode" valueName="ChatAgentMode">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="ChatMCP" class="Both" displayName="$(string.ChatMCP)" explainText="$(string.ChatMCP_chat_mcp_access)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatMCP)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<enum id="ChatMCP" valueName="ChatMCP">
<item displayName="$(string.ChatMCP_chat.mcp.access.none)"><value><string>none</string></value></item>
<item displayName="$(string.ChatMCP_chat.mcp.access.registry)"><value><string>registry</string></value></item>
<item displayName="$(string.ChatMCP_chat.mcp.access.any)"><value><string>all</string></value></item>
</enum>
</elements>
</policy>
<policy name="ChatPromptFiles" class="Both" displayName="$(string.ChatPromptFiles)" explainText="$(string.ChatPromptFiles_chat_promptFiles_policy)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatPromptFiles)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<boolean id="ChatPromptFiles" valueName="ChatPromptFiles">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="ChatToolsAutoApprove" class="Both" displayName="$(string.ChatToolsAutoApprove)" explainText="$(string.ChatToolsAutoApprove_autoApprove2_description)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatToolsAutoApprove)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<boolean id="ChatToolsAutoApprove" valueName="ChatToolsAutoApprove">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="McpGalleryServiceUrl" class="Both" displayName="$(string.McpGalleryServiceUrl)" explainText="$(string.McpGalleryServiceUrl_mcp_gallery_serviceUrl)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.McpGalleryServiceUrl)">
<parentCategory ref="interactiveSessionConfigurationTitle" />
<supportedOn ref="Supported_1_101" />
<elements>
<text id="McpGalleryServiceUrl" valueName="McpGalleryServiceUrl" required="true" />
</elements>
</policy>
<policy name="AllowedExtensions" class="Both" displayName="$(string.AllowedExtensions)" explainText="$(string.AllowedExtensions_extensions_allowed_policy)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.AllowedExtensions)">
<parentCategory ref="extensionsConfigurationTitle" />
<supportedOn ref="Supported_1_96" />
<elements>
<multiText id="AllowedExtensions" valueName="AllowedExtensions" required="true" />
</elements>
</policy>
<policy name="ExtensionGalleryServiceUrl" class="Both" displayName="$(string.ExtensionGalleryServiceUrl)" explainText="$(string.ExtensionGalleryServiceUrl_extensions_gallery_serviceUrl)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ExtensionGalleryServiceUrl)">
<parentCategory ref="extensionsConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<text id="ExtensionGalleryServiceUrl" valueName="ExtensionGalleryServiceUrl" required="true" />
</elements>
</policy>
<policy name="ChatToolsTerminalEnableAutoApprove" class="Both" displayName="$(string.ChatToolsTerminalEnableAutoApprove)" explainText="$(string.ChatToolsTerminalEnableAutoApprove_autoApproveMode_description)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.ChatToolsTerminalEnableAutoApprove)">
<parentCategory ref="terminalIntegratedConfigurationTitle" />
<supportedOn ref="Supported_1_104" />
<elements>
<boolean id="ChatToolsTerminalEnableAutoApprove" valueName="ChatToolsTerminalEnableAutoApprove">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="EnableFeedback" class="Both" displayName="$(string.EnableFeedback)" explainText="$(string.EnableFeedback_telemetry_feedback_enabled)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.EnableFeedback)">
<parentCategory ref="telemetryConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<boolean id="EnableFeedback" valueName="EnableFeedback">
<trueValue><decimal value="1" /></trueValue><falseValue><decimal value="0" /></falseValue>
</boolean>
</elements>
</policy>
<policy name="TelemetryLevel" class="Both" displayName="$(string.TelemetryLevel)" explainText="$(string.TelemetryLevel_telemetry_telemetryLevel_policyDescription)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.TelemetryLevel)">
<parentCategory ref="telemetryConfigurationTitle" />
<supportedOn ref="Supported_1_99" />
<elements>
<enum id="TelemetryLevel" valueName="TelemetryLevel">
<item displayName="$(string.TelemetryLevel_telemetry.telemetryLevel.default)"><value><string>all</string></value></item>
<item displayName="$(string.TelemetryLevel_telemetry.telemetryLevel.error)"><value><string>error</string></value></item>
<item displayName="$(string.TelemetryLevel_telemetry.telemetryLevel.crash)"><value><string>crash</string></value></item>
<item displayName="$(string.TelemetryLevel_telemetry.telemetryLevel.off)"><value><string>off</string></value></item>
</enum>
</elements>
</policy>
<policy name="UpdateMode" class="Both" displayName="$(string.UpdateMode)" explainText="$(string.UpdateMode_updateMode)" key="Software\Policies\Microsoft\CodeOSS" presentation="$(presentation.UpdateMode)">
<parentCategory ref="updateConfigurationTitle" />
<supportedOn ref="Supported_1_67" />
<elements>
<enum id="UpdateMode" valueName="UpdateMode">
<item displayName="$(string.UpdateMode_none)"><value><string>none</string></value></item>
<item displayName="$(string.UpdateMode_manual)"><value><string>manual</string></value></item>
<item displayName="$(string.UpdateMode_start)"><value><string>start</string></value></item>
<item displayName="$(string.UpdateMode_default)"><value><string>default</string></value></item>
</enum>
</elements>
</policy>
</policies>
</policyDefinitions>
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">Code - OSS</string>
<string id="Supported_1_101">Code - OSS &gt;= 1.101</string>
<string id="Supported_1_104">Code - OSS &gt;= 1.104</string>
<string id="Supported_1_67">Code - OSS &gt;= 1.67</string>
<string id="Supported_1_96">Code - OSS &gt;= 1.96</string>
<string id="Supported_1_99">Code - OSS &gt;= 1.99</string>
<string id="Category_interactiveSessionConfigurationTitle">Chat</string>
<string id="Category_extensionsConfigurationTitle">Extensions</string>
<string id="Category_terminalIntegratedConfigurationTitle">Integrated Terminal</string>
<string id="Category_telemetryConfigurationTitle">Telemetry</string>
<string id="Category_updateConfigurationTitle">Update</string>
<string id="ChatAgentExtensionTools">ChatAgentExtensionTools</string>
<string id="ChatAgentExtensionTools_chat_extensionToolsEnabled">Enable using tools contributed by third-party extensions.</string>
<string id="ChatAgentMode">ChatAgentMode</string>
<string id="ChatAgentMode_chat_agent_enabled_description">Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.</string>
<string id="ChatMCP">ChatMCP</string>
<string id="ChatMCP_chat_mcp_access">Controls access to installed Model Context Protocol servers.</string>
<string id="ChatMCP_chat_mcp_access_none">No access to MCP servers.</string>
<string id="ChatMCP_chat_mcp_access_registry">Allows access to MCP servers installed from the registry that VS Code is connected to.</string>
<string id="ChatMCP_chat_mcp_access_any">Allow access to any installed MCP server.</string>
<string id="ChatPromptFiles">ChatPromptFiles</string>
<string id="ChatPromptFiles_chat_promptFiles_policy">Enables reusable prompt and instruction files in Chat sessions.</string>
<string id="ChatToolsAutoApprove">ChatToolsAutoApprove</string>
<string id="ChatToolsAutoApprove_autoApprove2_description">Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.
This feature disables critical security protections and makes it much easier for an attacker to compromise the machine.</string>
<string id="McpGalleryServiceUrl">McpGalleryServiceUrl</string>
<string id="McpGalleryServiceUrl_mcp_gallery_serviceUrl">Configure the MCP Gallery service URL to connect to</string>
<string id="AllowedExtensions">AllowedExtensions</string>
<string id="AllowedExtensions_extensions_allowed_policy">Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions</string>
<string id="ExtensionGalleryServiceUrl">ExtensionGalleryServiceUrl</string>
<string id="ExtensionGalleryServiceUrl_extensions_gallery_serviceUrl">Configure the Marketplace service URL to connect to</string>
<string id="ChatToolsTerminalEnableAutoApprove">ChatToolsTerminalEnableAutoApprove</string>
<string id="ChatToolsTerminalEnableAutoApprove_autoApproveMode_description">Controls whether to allow auto approval in the run in terminal tool.</string>
<string id="EnableFeedback">EnableFeedback</string>
<string id="EnableFeedback_telemetry_feedback_enabled">Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.</string>
<string id="TelemetryLevel">TelemetryLevel</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_policyDescription">Controls the level of telemetry.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_default">Sends usage data, errors, and crash reports.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_error">Sends general error telemetry and crash reports.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_crash">Sends OS level crash reports.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_off">Disables all product telemetry.</string>
<string id="UpdateMode">UpdateMode</string>
<string id="UpdateMode_updateMode">Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.</string>
<string id="UpdateMode_none">Disable updates.</string>
<string id="UpdateMode_manual">Disable automatic background update checks. Updates will be available if you manually check for updates.</string>
<string id="UpdateMode_start">Check for updates only on startup. Disable automatic background update checks.</string>
<string id="UpdateMode_default">Enable automatic update checks. Code will check for updates automatically and periodically.</string>
</stringTable>
<presentationTable>
<presentation id="ChatAgentExtensionTools"><checkBox refId="ChatAgentExtensionTools">ChatAgentExtensionTools</checkBox></presentation>
<presentation id="ChatAgentMode"><checkBox refId="ChatAgentMode">ChatAgentMode</checkBox></presentation>
<presentation id="ChatMCP"><dropdownList refId="ChatMCP" /></presentation>
<presentation id="ChatPromptFiles"><checkBox refId="ChatPromptFiles">ChatPromptFiles</checkBox></presentation>
<presentation id="ChatToolsAutoApprove"><checkBox refId="ChatToolsAutoApprove">ChatToolsAutoApprove</checkBox></presentation>
<presentation id="McpGalleryServiceUrl"><textBox refId="McpGalleryServiceUrl"><label>McpGalleryServiceUrl:</label></textBox></presentation>
<presentation id="AllowedExtensions"><multiTextBox refId="AllowedExtensions" /></presentation>
<presentation id="ExtensionGalleryServiceUrl"><textBox refId="ExtensionGalleryServiceUrl"><label>ExtensionGalleryServiceUrl:</label></textBox></presentation>
<presentation id="ChatToolsTerminalEnableAutoApprove"><checkBox refId="ChatToolsTerminalEnableAutoApprove">ChatToolsTerminalEnableAutoApprove</checkBox></presentation>
<presentation id="EnableFeedback"><checkBox refId="EnableFeedback">EnableFeedback</checkBox></presentation>
<presentation id="TelemetryLevel"><dropdownList refId="TelemetryLevel" /></presentation>
<presentation id="UpdateMode"><dropdownList refId="UpdateMode" /></presentation>
</presentationTable>
</resources>
</policyDefinitionResources>
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<policyDefinitionResources revision="1.0" schemaVersion="1.0">
<displayName />
<description />
<resources>
<stringTable>
<string id="Application">Code - OSS</string>
<string id="Supported_1_101">Code - OSS &gt;= 1.101</string>
<string id="Supported_1_104">Code - OSS &gt;= 1.104</string>
<string id="Supported_1_67">Code - OSS &gt;= 1.67</string>
<string id="Supported_1_96">Code - OSS &gt;= 1.96</string>
<string id="Supported_1_99">Code - OSS &gt;= 1.99</string>
<string id="Category_interactiveSessionConfigurationTitle">Session interactive</string>
<string id="Category_extensionsConfigurationTitle">Extensions</string>
<string id="Category_terminalIntegratedConfigurationTitle">Terminal intégré</string>
<string id="Category_telemetryConfigurationTitle">Télémétrie</string>
<string id="Category_updateConfigurationTitle">Mettre à jour</string>
<string id="ChatAgentExtensionTools">ChatAgentExtensionTools</string>
<string id="ChatAgentExtensionTools_chat_extensionToolsEnabled">Autorisez lutilisation doutils fournis par des extensions tierces.</string>
<string id="ChatAgentMode">ChatAgentMode</string>
<string id="ChatAgentMode_chat_agent_enabled_description">Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.</string>
<string id="ChatMCP">ChatMCP</string>
<string id="ChatMCP_chat_mcp_access">Contrôle laccès aux serveurs de protocole de contexte du modèle.</string>
<string id="ChatMCP_chat_mcp_access_none">Aucun accès aux serveurs MCP.</string>
<string id="ChatMCP_chat_mcp_access_registry">Autorise laccès aux serveurs MCP installés à partir du registre auquel VS Code est connecté.</string>
<string id="ChatMCP_chat_mcp_access_any">Autorisez laccès à tout serveur MCP installé.</string>
<string id="ChatPromptFiles">ChatPromptFiles</string>
<string id="ChatPromptFiles_chat_promptFiles_policy">Active les fichiers dinstruction et de requête réutilisables dans les sessions Conversation.</string>
<string id="ChatToolsAutoApprove">ChatToolsAutoApprove</string>
<string id="ChatToolsAutoApprove_autoApprove2_description">Lapprobation automatique globale, également appelée « mode YOLO », désactive complètement lapprobation manuelle pour tous les outils dans tous les espaces de travail, permettant à lagent dagir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises.
Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.</string>
<string id="McpGalleryServiceUrl">McpGalleryServiceUrl</string>
<string id="McpGalleryServiceUrl_mcp_gallery_serviceUrl">Configurer lURL du service de la galerie MCP à laquelle se connecter</string>
<string id="AllowedExtensions">AllowedExtensions</string>
<string id="AllowedExtensions_extensions_allowed_policy">Spécifiez une liste dextensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant lutilisation dextensions non autorisées. Plus dinformations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions</string>
<string id="ExtensionGalleryServiceUrl">ExtensionGalleryServiceUrl</string>
<string id="ExtensionGalleryServiceUrl_extensions_gallery_serviceUrl">Configurer lURL du service Place de marché à laquelle se connecter</string>
<string id="ChatToolsTerminalEnableAutoApprove">ChatToolsTerminalEnableAutoApprove</string>
<string id="ChatToolsTerminalEnableAutoApprove_autoApproveMode_description">Contrôle sil faut autoriser lapprobation automatique lors de lexécution dans loutil terminal.</string>
<string id="EnableFeedback">EnableFeedback</string>
<string id="EnableFeedback_telemetry_feedback_enabled">Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.</string>
<string id="TelemetryLevel">TelemetryLevel</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_policyDescription">Contrôle le niveau de télémétrie.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_default">Envoie les données d'utilisation, les erreurs et les rapports d'erreur.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_error">Envoie la télémétrie d'erreur générale et les rapports de plantage.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_crash">Envoie des rapports de plantage au niveau du système d'exploitation.</string>
<string id="TelemetryLevel_telemetry_telemetryLevel_off">Désactive toutes les données de télémétrie du produit.</string>
<string id="UpdateMode">UpdateMode</string>
<string id="UpdateMode_updateMode">Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.</string>
<string id="UpdateMode_none">Aucun</string>
<string id="UpdateMode_manual">Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement.</string>
<string id="UpdateMode_start">Démarrer</string>
<string id="UpdateMode_default">Système</string>
</stringTable>
<presentationTable>
<presentation id="ChatAgentExtensionTools"><checkBox refId="ChatAgentExtensionTools">ChatAgentExtensionTools</checkBox></presentation>
<presentation id="ChatAgentMode"><checkBox refId="ChatAgentMode">ChatAgentMode</checkBox></presentation>
<presentation id="ChatMCP"><dropdownList refId="ChatMCP" /></presentation>
<presentation id="ChatPromptFiles"><checkBox refId="ChatPromptFiles">ChatPromptFiles</checkBox></presentation>
<presentation id="ChatToolsAutoApprove"><checkBox refId="ChatToolsAutoApprove">ChatToolsAutoApprove</checkBox></presentation>
<presentation id="McpGalleryServiceUrl"><textBox refId="McpGalleryServiceUrl"><label>McpGalleryServiceUrl:</label></textBox></presentation>
<presentation id="AllowedExtensions"><multiTextBox refId="AllowedExtensions" /></presentation>
<presentation id="ExtensionGalleryServiceUrl"><textBox refId="ExtensionGalleryServiceUrl"><label>ExtensionGalleryServiceUrl:</label></textBox></presentation>
<presentation id="ChatToolsTerminalEnableAutoApprove"><checkBox refId="ChatToolsTerminalEnableAutoApprove">ChatToolsTerminalEnableAutoApprove</checkBox></presentation>
<presentation id="EnableFeedback"><checkBox refId="EnableFeedback">EnableFeedback</checkBox></presentation>
<presentation id="TelemetryLevel"><dropdownList refId="TelemetryLevel" /></presentation>
<presentation id="UpdateMode"><dropdownList refId="UpdateMode" /></presentation>
</presentationTable>
</resources>
</policyDefinitionResources>
+119
View File
@@ -0,0 +1,119 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const numberPolicy_js_1 = require("../policies/numberPolicy.js");
const types_js_1 = require("../policies/types.js");
suite('NumberPolicy', () => {
const mockCategory = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy = {
key: 'test.number.policy',
name: 'TestNumberPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'number',
default: 42,
localization: {
description: { key: 'test.policy.description', value: 'Test number policy description' }
}
};
test('should create NumberPolicy from factory method', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
assert_1.default.strictEqual(policy.name, 'TestNumberPolicy');
assert_1.default.strictEqual(policy.minimumVersion, '1.0');
assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value);
assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Number);
});
test('should render ADMX elements correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admx = policy.renderADMX('TestKey');
assert_1.default.deepStrictEqual(admx, [
'<policy name="TestNumberPolicy" class="Both" displayName="$(string.TestNumberPolicy)" explainText="$(string.TestNumberPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestNumberPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<decimal id="TestNumberPolicy" valueName="TestNumberPolicy" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestNumberPolicy">TestNumberPolicy</string>',
'<string id="TestNumberPolicy_test_policy_description">Test number policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestNumberPolicy">TestNumberPolicy</string>',
'<string id="TestNumberPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const presentation = policy.renderADMLPresentation();
assert_1.default.strictEqual(presentation, '<presentation id="TestNumberPolicy"><decimalTextBox refId="TestNumberPolicy" defaultValue="42">TestNumberPolicy</decimalTextBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profileValue = policy.renderProfileValue();
assert_1.default.strictEqual(profileValue, '<integer>42</integer>');
});
test('should render profile correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profile = policy.renderProfile();
assert_1.default.strictEqual(profile.length, 2);
assert_1.default.strictEqual(profile[0], '<key>TestNumberPolicy</key>');
assert_1.default.strictEqual(profile[1], '<integer>42</integer>');
});
test('should render profile manifest value correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Test number policy description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>');
});
test('should render profile manifest value with translations', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>');
});
test('should render profile manifest correctly', () => {
const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifest = policy.renderProfileManifest();
assert_1.default.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Test number policy description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>\n</dict>');
});
});
//# sourceMappingURL=numberPolicy.test.js.map
+157
View File
@@ -0,0 +1,157 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { NumberPolicy } from '../policies/numberPolicy.js';
import { LanguageTranslations, PolicyType } from '../policies/types.js';
import { CategoryDto, PolicyDto } from '../policies/policyDto.js';
suite('NumberPolicy', () => {
const mockCategory: CategoryDto = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy: PolicyDto = {
key: 'test.number.policy',
name: 'TestNumberPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'number',
default: 42,
localization: {
description: { key: 'test.policy.description', value: 'Test number policy description' }
}
};
test('should create NumberPolicy from factory method', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
assert.strictEqual(policy.name, 'TestNumberPolicy');
assert.strictEqual(policy.minimumVersion, '1.0');
assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert.strictEqual(policy.category.name.value, mockCategory.name.value);
assert.strictEqual(policy.type, PolicyType.Number);
});
test('should render ADMX elements correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admx = policy.renderADMX('TestKey');
assert.deepStrictEqual(admx, [
'<policy name="TestNumberPolicy" class="Both" displayName="$(string.TestNumberPolicy)" explainText="$(string.TestNumberPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestNumberPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<decimal id="TestNumberPolicy" valueName="TestNumberPolicy" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert.deepStrictEqual(admlStrings, [
'<string id="TestNumberPolicy">TestNumberPolicy</string>',
'<string id="TestNumberPolicy_test_policy_description">Test number policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert.deepStrictEqual(admlStrings, [
'<string id="TestNumberPolicy">TestNumberPolicy</string>',
'<string id="TestNumberPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const presentation = policy.renderADMLPresentation();
assert.strictEqual(presentation, '<presentation id="TestNumberPolicy"><decimalTextBox refId="TestNumberPolicy" defaultValue="42">TestNumberPolicy</decimalTextBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profileValue = policy.renderProfileValue();
assert.strictEqual(profileValue, '<integer>42</integer>');
});
test('should render profile correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profile = policy.renderProfile();
assert.strictEqual(profile.length, 2);
assert.strictEqual(profile[0], '<key>TestNumberPolicy</key>');
assert.strictEqual(profile[1], '<integer>42</integer>');
});
test('should render profile manifest value correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Test number policy description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>');
});
test('should render profile manifest value with translations', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>');
});
test('should render profile manifest correctly', () => {
const policy = NumberPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifest = policy.renderProfileManifest();
assert.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<integer>42</integer>\n<key>pfm_description</key>\n<string>Test number policy description</string>\n<key>pfm_name</key>\n<string>TestNumberPolicy</string>\n<key>pfm_title</key>\n<string>TestNumberPolicy</string>\n<key>pfm_type</key>\n<string>integer</string>\n</dict>');
});
});
+118
View File
@@ -0,0 +1,118 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const objectPolicy_js_1 = require("../policies/objectPolicy.js");
const types_js_1 = require("../policies/types.js");
suite('ObjectPolicy', () => {
const mockCategory = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy = {
key: 'test.object.policy',
name: 'TestObjectPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'object',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' }
}
};
test('should create ObjectPolicy from factory method', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
assert_1.default.strictEqual(policy.name, 'TestObjectPolicy');
assert_1.default.strictEqual(policy.minimumVersion, '1.0');
assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value);
assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Object);
});
test('should render ADMX elements correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admx = policy.renderADMX('TestKey');
assert_1.default.deepStrictEqual(admx, [
'<policy name="TestObjectPolicy" class="Both" displayName="$(string.TestObjectPolicy)" explainText="$(string.TestObjectPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestObjectPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<multiText id="TestObjectPolicy" valueName="TestObjectPolicy" required="true" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestObjectPolicy">TestObjectPolicy</string>',
'<string id="TestObjectPolicy_test_policy_description">Test policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestObjectPolicy">TestObjectPolicy</string>',
'<string id="TestObjectPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const presentation = policy.renderADMLPresentation();
assert_1.default.strictEqual(presentation, '<presentation id="TestObjectPolicy"><multiTextBox refId="TestObjectPolicy" /></presentation>');
});
test('should render profile value correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profileValue = policy.renderProfileValue();
assert_1.default.strictEqual(profileValue, '<string></string>');
});
test('should render profile correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profile = policy.renderProfile();
assert_1.default.strictEqual(profile.length, 2);
assert_1.default.strictEqual(profile[0], '<key>TestObjectPolicy</key>');
assert_1.default.strictEqual(profile[1], '<string></string>');
});
test('should render profile manifest value correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n');
});
test('should render profile manifest value with translations', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n');
});
test('should render profile manifest correctly', () => {
const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifest = policy.renderProfileManifest();
assert_1.default.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n\n</dict>');
});
});
//# sourceMappingURL=objectPolicy.test.js.map
+156
View File
@@ -0,0 +1,156 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { ObjectPolicy } from '../policies/objectPolicy.js';
import { LanguageTranslations, PolicyType } from '../policies/types.js';
import { CategoryDto, PolicyDto } from '../policies/policyDto.js';
suite('ObjectPolicy', () => {
const mockCategory: CategoryDto = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy: PolicyDto = {
key: 'test.object.policy',
name: 'TestObjectPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'object',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' }
}
};
test('should create ObjectPolicy from factory method', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
assert.strictEqual(policy.name, 'TestObjectPolicy');
assert.strictEqual(policy.minimumVersion, '1.0');
assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert.strictEqual(policy.category.name.value, mockCategory.name.value);
assert.strictEqual(policy.type, PolicyType.Object);
});
test('should render ADMX elements correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admx = policy.renderADMX('TestKey');
assert.deepStrictEqual(admx, [
'<policy name="TestObjectPolicy" class="Both" displayName="$(string.TestObjectPolicy)" explainText="$(string.TestObjectPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestObjectPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<multiText id="TestObjectPolicy" valueName="TestObjectPolicy" required="true" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert.deepStrictEqual(admlStrings, [
'<string id="TestObjectPolicy">TestObjectPolicy</string>',
'<string id="TestObjectPolicy_test_policy_description">Test policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert.deepStrictEqual(admlStrings, [
'<string id="TestObjectPolicy">TestObjectPolicy</string>',
'<string id="TestObjectPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const presentation = policy.renderADMLPresentation();
assert.strictEqual(presentation, '<presentation id="TestObjectPolicy"><multiTextBox refId="TestObjectPolicy" /></presentation>');
});
test('should render profile value correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profileValue = policy.renderProfileValue();
assert.strictEqual(profileValue, '<string></string>');
});
test('should render profile correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profile = policy.renderProfile();
assert.strictEqual(profile.length, 2);
assert.strictEqual(profile[0], '<key>TestObjectPolicy</key>');
assert.strictEqual(profile[1], '<string></string>');
});
test('should render profile manifest value correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n');
});
test('should render profile manifest value with translations', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n');
});
test('should render profile manifest correctly', () => {
const policy = ObjectPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifest = policy.renderProfileManifest();
assert.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestObjectPolicy</string>\n<key>pfm_title</key>\n<string>TestObjectPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n\n</dict>');
});
});
+455
View File
@@ -0,0 +1,455 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const booleanPolicy_1 = require("../policies/booleanPolicy");
const numberPolicy_1 = require("../policies/numberPolicy");
const objectPolicy_1 = require("../policies/objectPolicy");
const stringEnumPolicy_1 = require("../policies/stringEnumPolicy");
const stringPolicy_1 = require("../policies/stringPolicy");
const render_1 = require("../policies/render");
const PolicyTypes = [
booleanPolicy_1.BooleanPolicy,
numberPolicy_1.NumberPolicy,
stringEnumPolicy_1.StringEnumPolicy,
stringPolicy_1.StringPolicy,
objectPolicy_1.ObjectPolicy
];
function parsePolicies(policyData) {
const categories = new Map();
for (const category of policyData.categories) {
categories.set(category.key, category);
}
const policies = [];
for (const policy of policyData.policies) {
const category = categories.get(policy.category);
if (!category) {
throw new Error(`Unknown category: ${policy.category}`);
}
let result;
for (const policyType of PolicyTypes) {
if (result = policyType.from(category, policy)) {
break;
}
}
if (!result) {
throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`);
}
policies.push(result);
}
// Sort policies first by category name, then by policy name
policies.sort((a, b) => {
const categoryCompare = a.category.name.value.localeCompare(b.category.name.value);
if (categoryCompare !== 0) {
return categoryCompare;
}
return a.name.localeCompare(b.name);
});
return policies;
}
/**
* This is a snapshot of the data taken on Oct. 20 2025 as part of the
* policy refactor effort. Let's make sure that nothing has regressed.
*/
const policies = {
categories: [
{
key: 'Extensions',
name: {
key: 'extensionsConfigurationTitle',
value: 'Extensions'
}
},
{
key: 'IntegratedTerminal',
name: {
key: 'terminalIntegratedConfigurationTitle',
value: 'Integrated Terminal'
}
},
{
key: 'InteractiveSession',
name: {
key: 'interactiveSessionConfigurationTitle',
value: 'Chat'
}
},
{
key: 'Telemetry',
name: {
key: 'telemetryConfigurationTitle',
value: 'Telemetry'
}
},
{
key: 'Update',
name: {
key: 'updateConfigurationTitle',
value: 'Update'
}
}
],
policies: [
{
key: 'chat.mcp.gallery.serviceUrl',
name: 'McpGalleryServiceUrl',
category: 'InteractiveSession',
minimumVersion: '1.101',
localization: {
description: {
key: 'mcp.gallery.serviceUrl',
value: 'Configure the MCP Gallery service URL to connect to'
}
},
type: 'string',
default: ''
},
{
key: 'extensions.gallery.serviceUrl',
name: 'ExtensionGalleryServiceUrl',
category: 'Extensions',
minimumVersion: '1.99',
localization: {
description: {
key: 'extensions.gallery.serviceUrl',
value: 'Configure the Marketplace service URL to connect to'
}
},
type: 'string',
default: ''
},
{
key: 'extensions.allowed',
name: 'AllowedExtensions',
category: 'Extensions',
minimumVersion: '1.96',
localization: {
description: {
key: 'extensions.allowed.policy',
value: 'Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions'
}
},
type: 'object',
default: '*'
},
{
key: 'chat.tools.global.autoApprove',
name: 'ChatToolsAutoApprove',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'autoApprove2.description',
value: 'Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.\n\nThis feature disables critical security protections and makes it much easier for an attacker to compromise the machine.'
}
},
type: 'boolean',
default: false
},
{
key: 'chat.mcp.access',
name: 'ChatMCP',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.mcp.access',
value: 'Controls access to installed Model Context Protocol servers.'
},
enumDescriptions: [
{
key: 'chat.mcp.access.none',
value: 'No access to MCP servers.'
},
{
key: 'chat.mcp.access.registry',
value: 'Allows access to MCP servers installed from the registry that VS Code is connected to.'
},
{
key: 'chat.mcp.access.any',
value: 'Allow access to any installed MCP server.'
}
]
},
type: 'string',
default: 'all',
enum: [
'none',
'registry',
'all'
]
},
{
key: 'chat.extensionTools.enabled',
name: 'ChatAgentExtensionTools',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.extensionToolsEnabled',
value: 'Enable using tools contributed by third-party extensions.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.agent.enabled',
name: 'ChatAgentMode',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.agent.enabled.description',
value: 'Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.promptFiles',
name: 'ChatPromptFiles',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.promptFiles.policy',
value: 'Enables reusable prompt and instruction files in Chat sessions.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.tools.terminal.enableAutoApprove',
name: 'ChatToolsTerminalEnableAutoApprove',
category: 'IntegratedTerminal',
minimumVersion: '1.104',
localization: {
description: {
key: 'autoApproveMode.description',
value: 'Controls whether to allow auto approval in the run in terminal tool.'
}
},
type: 'boolean',
default: true
},
{
key: 'update.mode',
name: 'UpdateMode',
category: 'Update',
minimumVersion: '1.67',
localization: {
description: {
key: 'updateMode',
value: 'Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.'
},
enumDescriptions: [
{
key: 'none',
value: 'Disable updates.'
},
{
key: 'manual',
value: 'Disable automatic background update checks. Updates will be available if you manually check for updates.'
},
{
key: 'start',
value: 'Check for updates only on startup. Disable automatic background update checks.'
},
{
key: 'default',
value: 'Enable automatic update checks. Code will check for updates automatically and periodically.'
}
]
},
type: 'string',
default: 'default',
enum: [
'none',
'manual',
'start',
'default'
]
},
{
key: 'telemetry.telemetryLevel',
name: 'TelemetryLevel',
category: 'Telemetry',
minimumVersion: '1.99',
localization: {
description: {
key: 'telemetry.telemetryLevel.policyDescription',
value: 'Controls the level of telemetry.'
},
enumDescriptions: [
{
key: 'telemetry.telemetryLevel.default',
value: 'Sends usage data, errors, and crash reports.'
},
{
key: 'telemetry.telemetryLevel.error',
value: 'Sends general error telemetry and crash reports.'
},
{
key: 'telemetry.telemetryLevel.crash',
value: 'Sends OS level crash reports.'
},
{
key: 'telemetry.telemetryLevel.off',
value: 'Disables all product telemetry.'
}
]
},
type: 'string',
default: 'all',
enum: [
'all',
'error',
'crash',
'off'
]
},
{
key: 'telemetry.feedback.enabled',
name: 'EnableFeedback',
category: 'Telemetry',
minimumVersion: '1.99',
localization: {
description: {
key: 'telemetry.feedback.enabled',
value: 'Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.'
}
},
type: 'boolean',
default: true
}
]
};
const mockProduct = {
nameLong: 'Code - OSS',
darwinBundleIdentifier: 'com.visualstudio.code.oss',
darwinProfilePayloadUUID: 'CF808BE7-53F3-46C6-A7E2-7EDB98A5E959',
darwinProfileUUID: '47827DD9-4734-49A0-AF80-7E19B11495CC',
win32RegValueName: 'CodeOSS'
};
const frenchTranslations = [
{
languageId: 'fr-fr',
languageTranslations: {
'': {
'interactiveSessionConfigurationTitle': 'Session interactive',
'extensionsConfigurationTitle': 'Extensions',
'terminalIntegratedConfigurationTitle': 'Terminal intégré',
'telemetryConfigurationTitle': 'Télémétrie',
'updateConfigurationTitle': 'Mettre à jour',
'chat.extensionToolsEnabled': 'Autorisez lutilisation doutils fournis par des extensions tierces.',
'chat.agent.enabled.description': 'Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.',
'chat.mcp.access': 'Contrôle laccès aux serveurs de protocole de contexte du modèle.',
'chat.mcp.access.none': 'Aucun accès aux serveurs MCP.',
'chat.mcp.access.registry': `Autorise laccès aux serveurs MCP installés à partir du registre auquel VS Code est connecté.`,
'chat.mcp.access.any': 'Autorisez laccès à tout serveur MCP installé.',
'chat.promptFiles.policy': 'Active les fichiers dinstruction et de requête réutilisables dans les sessions Conversation.',
'autoApprove2.description': `Lapprobation automatique globale, également appelée « mode YOLO », désactive complètement lapprobation manuelle pour tous les outils dans tous les espaces de travail, permettant à lagent dagir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises.
Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.`,
'mcp.gallery.serviceUrl': 'Configurer lURL du service de la galerie MCP à laquelle se connecter',
'extensions.allowed.policy': 'Spécifiez une liste dextensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant lutilisation dextensions non autorisées. Plus dinformations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions',
'extensions.gallery.serviceUrl': 'Configurer lURL du service Place de marché à laquelle se connecter',
'autoApproveMode.description': 'Contrôle sil faut autoriser lapprobation automatique lors de lexécution dans loutil terminal.',
'telemetry.feedback.enabled': 'Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.',
'telemetry.telemetryLevel.policyDescription': 'Contrôle le niveau de télémétrie.',
'telemetry.telemetryLevel.default': `Envoie les données d'utilisation, les erreurs et les rapports d'erreur.`,
'telemetry.telemetryLevel.error': `Envoie la télémétrie d'erreur générale et les rapports de plantage.`,
'telemetry.telemetryLevel.crash': `Envoie des rapports de plantage au niveau du système d'exploitation.`,
'telemetry.telemetryLevel.off': 'Désactive toutes les données de télémétrie du produit.',
'updateMode': `Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.`,
'none': 'Aucun',
'manual': 'Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement.',
'start': 'Démarrer',
'default': 'Système'
}
}
}
];
suite('Policy E2E conversion', () => {
test('should render macOS policy profile from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'com.visualstudio.code.oss.mobileconfig');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Compare the rendered profile with the fixture
assert_1.default.strictEqual(result.profile, expectedContent, 'macOS policy profile should match the fixture');
});
test('should render macOS manifest from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'en-us', 'com.visualstudio.code.oss.plist');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Find the en-us manifest
const enUsManifest = result.manifests.find(m => m.languageId === 'en-us');
assert_1.default.ok(enUsManifest, 'en-us manifest should exist');
// Compare the rendered manifest with the fixture, ignoring the timestamp
// The pfm_last_modified field contains a timestamp that will differ each time
const normalizeTimestamp = (content) => content.replace(/<date>.*?<\/date>/, '<date>TIMESTAMP</date>');
assert_1.default.strictEqual(normalizeTimestamp(enUsManifest.contents), normalizeTimestamp(expectedContent), 'macOS manifest should match the fixture (ignoring timestamp)');
});
test('should render Windows ADMX from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'CodeOSS.admx');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Compare the rendered ADMX with the fixture
assert_1.default.strictEqual(result.admx, expectedContent, 'Windows ADMX should match the fixture');
});
test('should render Windows ADML from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'en-us', 'CodeOSS.adml');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Find the en-us ADML
const enUsAdml = result.adml.find(a => a.languageId === 'en-us');
assert_1.default.ok(enUsAdml, 'en-us ADML should exist');
// Compare the rendered ADML with the fixture
assert_1.default.strictEqual(enUsAdml.contents, expectedContent, 'Windows ADML should match the fixture');
});
test('should render macOS manifest with fr-fr locale', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, frenchTranslations);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'fr-fr', 'com.visualstudio.code.oss.plist');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Find the fr-fr manifest
const frFrManifest = result.manifests.find(m => m.languageId === 'fr-fr');
assert_1.default.ok(frFrManifest, 'fr-fr manifest should exist');
// Compare the rendered manifest with the fixture, ignoring the timestamp
const normalizeTimestamp = (content) => content.replace(/<date>.*?<\/date>/, '<date>TIMESTAMP</date>');
assert_1.default.strictEqual(normalizeTimestamp(frFrManifest.contents), normalizeTimestamp(expectedContent), 'macOS fr-fr manifest should match the fixture (ignoring timestamp)');
});
test('should render Windows ADML with fr-fr locale', async () => {
const parsedPolicies = parsePolicies(policies);
const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, frenchTranslations);
// Load the expected fixture file
const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'fr-fr', 'CodeOSS.adml');
const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8');
// Find the fr-fr ADML
const frFrAdml = result.adml.find(a => a.languageId === 'fr-fr');
assert_1.default.ok(frFrAdml, 'fr-fr ADML should exist');
// Compare the rendered ADML with the fixture
assert_1.default.strictEqual(frFrAdml.contents, expectedContent, 'Windows fr-fr ADML should match the fixture');
});
});
//# sourceMappingURL=policyConversion.test.js.map
+495
View File
@@ -0,0 +1,495 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { promises as fs } from 'fs';
import path from 'path';
import { ExportedPolicyDataDto, CategoryDto } from '../policies/policyDto';
import { BooleanPolicy } from '../policies/booleanPolicy';
import { NumberPolicy } from '../policies/numberPolicy';
import { ObjectPolicy } from '../policies/objectPolicy';
import { StringEnumPolicy } from '../policies/stringEnumPolicy';
import { StringPolicy } from '../policies/stringPolicy';
import { Policy, ProductJson } from '../policies/types';
import { renderGP, renderMacOSPolicy } from '../policies/render';
const PolicyTypes = [
BooleanPolicy,
NumberPolicy,
StringEnumPolicy,
StringPolicy,
ObjectPolicy
];
function parsePolicies(policyData: ExportedPolicyDataDto): Policy[] {
const categories = new Map<string, CategoryDto>();
for (const category of policyData.categories) {
categories.set(category.key, category);
}
const policies: Policy[] = [];
for (const policy of policyData.policies) {
const category = categories.get(policy.category);
if (!category) {
throw new Error(`Unknown category: ${policy.category}`);
}
let result: Policy | undefined;
for (const policyType of PolicyTypes) {
if (result = policyType.from(category, policy)) {
break;
}
}
if (!result) {
throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`);
}
policies.push(result);
}
// Sort policies first by category name, then by policy name
policies.sort((a, b) => {
const categoryCompare = a.category.name.value.localeCompare(b.category.name.value);
if (categoryCompare !== 0) {
return categoryCompare;
}
return a.name.localeCompare(b.name);
});
return policies;
}
/**
* This is a snapshot of the data taken on Oct. 20 2025 as part of the
* policy refactor effort. Let's make sure that nothing has regressed.
*/
const policies: ExportedPolicyDataDto = {
categories: [
{
key: 'Extensions',
name: {
key: 'extensionsConfigurationTitle',
value: 'Extensions'
}
},
{
key: 'IntegratedTerminal',
name: {
key: 'terminalIntegratedConfigurationTitle',
value: 'Integrated Terminal'
}
},
{
key: 'InteractiveSession',
name: {
key: 'interactiveSessionConfigurationTitle',
value: 'Chat'
}
},
{
key: 'Telemetry',
name: {
key: 'telemetryConfigurationTitle',
value: 'Telemetry'
}
},
{
key: 'Update',
name: {
key: 'updateConfigurationTitle',
value: 'Update'
}
}
],
policies: [
{
key: 'chat.mcp.gallery.serviceUrl',
name: 'McpGalleryServiceUrl',
category: 'InteractiveSession',
minimumVersion: '1.101',
localization: {
description: {
key: 'mcp.gallery.serviceUrl',
value: 'Configure the MCP Gallery service URL to connect to'
}
},
type: 'string',
default: ''
},
{
key: 'extensions.gallery.serviceUrl',
name: 'ExtensionGalleryServiceUrl',
category: 'Extensions',
minimumVersion: '1.99',
localization: {
description: {
key: 'extensions.gallery.serviceUrl',
value: 'Configure the Marketplace service URL to connect to'
}
},
type: 'string',
default: ''
},
{
key: 'extensions.allowed',
name: 'AllowedExtensions',
category: 'Extensions',
minimumVersion: '1.96',
localization: {
description: {
key: 'extensions.allowed.policy',
value: 'Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions'
}
},
type: 'object',
default: '*'
},
{
key: 'chat.tools.global.autoApprove',
name: 'ChatToolsAutoApprove',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'autoApprove2.description',
value: 'Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.\n\nThis feature disables critical security protections and makes it much easier for an attacker to compromise the machine.'
}
},
type: 'boolean',
default: false
},
{
key: 'chat.mcp.access',
name: 'ChatMCP',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.mcp.access',
value: 'Controls access to installed Model Context Protocol servers.'
},
enumDescriptions: [
{
key: 'chat.mcp.access.none',
value: 'No access to MCP servers.'
},
{
key: 'chat.mcp.access.registry',
value: 'Allows access to MCP servers installed from the registry that VS Code is connected to.'
},
{
key: 'chat.mcp.access.any',
value: 'Allow access to any installed MCP server.'
}
]
},
type: 'string',
default: 'all',
enum: [
'none',
'registry',
'all'
]
},
{
key: 'chat.extensionTools.enabled',
name: 'ChatAgentExtensionTools',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.extensionToolsEnabled',
value: 'Enable using tools contributed by third-party extensions.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.agent.enabled',
name: 'ChatAgentMode',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.agent.enabled.description',
value: 'Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.promptFiles',
name: 'ChatPromptFiles',
category: 'InteractiveSession',
minimumVersion: '1.99',
localization: {
description: {
key: 'chat.promptFiles.policy',
value: 'Enables reusable prompt and instruction files in Chat sessions.'
}
},
type: 'boolean',
default: true
},
{
key: 'chat.tools.terminal.enableAutoApprove',
name: 'ChatToolsTerminalEnableAutoApprove',
category: 'IntegratedTerminal',
minimumVersion: '1.104',
localization: {
description: {
key: 'autoApproveMode.description',
value: 'Controls whether to allow auto approval in the run in terminal tool.'
}
},
type: 'boolean',
default: true
},
{
key: 'update.mode',
name: 'UpdateMode',
category: 'Update',
minimumVersion: '1.67',
localization: {
description: {
key: 'updateMode',
value: 'Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.'
},
enumDescriptions: [
{
key: 'none',
value: 'Disable updates.'
},
{
key: 'manual',
value: 'Disable automatic background update checks. Updates will be available if you manually check for updates.'
},
{
key: 'start',
value: 'Check for updates only on startup. Disable automatic background update checks.'
},
{
key: 'default',
value: 'Enable automatic update checks. Code will check for updates automatically and periodically.'
}
]
},
type: 'string',
default: 'default',
enum: [
'none',
'manual',
'start',
'default'
]
},
{
key: 'telemetry.telemetryLevel',
name: 'TelemetryLevel',
category: 'Telemetry',
minimumVersion: '1.99',
localization: {
description: {
key: 'telemetry.telemetryLevel.policyDescription',
value: 'Controls the level of telemetry.'
},
enumDescriptions: [
{
key: 'telemetry.telemetryLevel.default',
value: 'Sends usage data, errors, and crash reports.'
},
{
key: 'telemetry.telemetryLevel.error',
value: 'Sends general error telemetry and crash reports.'
},
{
key: 'telemetry.telemetryLevel.crash',
value: 'Sends OS level crash reports.'
},
{
key: 'telemetry.telemetryLevel.off',
value: 'Disables all product telemetry.'
}
]
},
type: 'string',
default: 'all',
enum: [
'all',
'error',
'crash',
'off'
]
},
{
key: 'telemetry.feedback.enabled',
name: 'EnableFeedback',
category: 'Telemetry',
minimumVersion: '1.99',
localization: {
description: {
key: 'telemetry.feedback.enabled',
value: 'Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.'
}
},
type: 'boolean',
default: true
}
]
};
const mockProduct: ProductJson = {
nameLong: 'Code - OSS',
darwinBundleIdentifier: 'com.visualstudio.code.oss',
darwinProfilePayloadUUID: 'CF808BE7-53F3-46C6-A7E2-7EDB98A5E959',
darwinProfileUUID: '47827DD9-4734-49A0-AF80-7E19B11495CC',
win32RegValueName: 'CodeOSS'
};
const frenchTranslations = [
{
languageId: 'fr-fr',
languageTranslations: {
'': {
'interactiveSessionConfigurationTitle': 'Session interactive',
'extensionsConfigurationTitle': 'Extensions',
'terminalIntegratedConfigurationTitle': 'Terminal intégré',
'telemetryConfigurationTitle': 'Télémétrie',
'updateConfigurationTitle': 'Mettre à jour',
'chat.extensionToolsEnabled': 'Autorisez lutilisation doutils fournis par des extensions tierces.',
'chat.agent.enabled.description': 'Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.',
'chat.mcp.access': 'Contrôle laccès aux serveurs de protocole de contexte du modèle.',
'chat.mcp.access.none': 'Aucun accès aux serveurs MCP.',
'chat.mcp.access.registry': `Autorise laccès aux serveurs MCP installés à partir du registre auquel VS Code est connecté.`,
'chat.mcp.access.any': 'Autorisez laccès à tout serveur MCP installé.',
'chat.promptFiles.policy': 'Active les fichiers dinstruction et de requête réutilisables dans les sessions Conversation.',
'autoApprove2.description': `Lapprobation automatique globale, également appelée « mode YOLO », désactive complètement lapprobation manuelle pour tous les outils dans tous les espaces de travail, permettant à lagent dagir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises.
Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.`,
'mcp.gallery.serviceUrl': 'Configurer lURL du service de la galerie MCP à laquelle se connecter',
'extensions.allowed.policy': 'Spécifiez une liste dextensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant lutilisation dextensions non autorisées. Plus dinformations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions',
'extensions.gallery.serviceUrl': 'Configurer lURL du service Place de marché à laquelle se connecter',
'autoApproveMode.description': 'Contrôle sil faut autoriser lapprobation automatique lors de lexécution dans loutil terminal.',
'telemetry.feedback.enabled': 'Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.',
'telemetry.telemetryLevel.policyDescription': 'Contrôle le niveau de télémétrie.',
'telemetry.telemetryLevel.default': `Envoie les données d'utilisation, les erreurs et les rapports d'erreur.`,
'telemetry.telemetryLevel.error': `Envoie la télémétrie d'erreur générale et les rapports de plantage.`,
'telemetry.telemetryLevel.crash': `Envoie des rapports de plantage au niveau du système d'exploitation.`,
'telemetry.telemetryLevel.off': 'Désactive toutes les données de télémétrie du produit.',
'updateMode': `Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.`,
'none': 'Aucun',
'manual': 'Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement.',
'start': 'Démarrer',
'default': 'Système'
}
}
}
];
suite('Policy E2E conversion', () => {
test('should render macOS policy profile from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderMacOSPolicy(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'com.visualstudio.code.oss.mobileconfig');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Compare the rendered profile with the fixture
assert.strictEqual(result.profile, expectedContent, 'macOS policy profile should match the fixture');
});
test('should render macOS manifest from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderMacOSPolicy(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'en-us', 'com.visualstudio.code.oss.plist');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Find the en-us manifest
const enUsManifest = result.manifests.find(m => m.languageId === 'en-us');
assert.ok(enUsManifest, 'en-us manifest should exist');
// Compare the rendered manifest with the fixture, ignoring the timestamp
// The pfm_last_modified field contains a timestamp that will differ each time
const normalizeTimestamp = (content: string) => content.replace(/<date>.*?<\/date>/, '<date>TIMESTAMP</date>');
assert.strictEqual(
normalizeTimestamp(enUsManifest.contents),
normalizeTimestamp(expectedContent),
'macOS manifest should match the fixture (ignoring timestamp)'
);
});
test('should render Windows ADMX from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderGP(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'CodeOSS.admx');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Compare the rendered ADMX with the fixture
assert.strictEqual(result.admx, expectedContent, 'Windows ADMX should match the fixture');
});
test('should render Windows ADML from policies list', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderGP(mockProduct, parsedPolicies, []);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'en-us', 'CodeOSS.adml');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Find the en-us ADML
const enUsAdml = result.adml.find(a => a.languageId === 'en-us');
assert.ok(enUsAdml, 'en-us ADML should exist');
// Compare the rendered ADML with the fixture
assert.strictEqual(enUsAdml.contents, expectedContent, 'Windows ADML should match the fixture');
});
test('should render macOS manifest with fr-fr locale', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderMacOSPolicy(mockProduct, parsedPolicies, frenchTranslations);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'fr-fr', 'com.visualstudio.code.oss.plist');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Find the fr-fr manifest
const frFrManifest = result.manifests.find(m => m.languageId === 'fr-fr');
assert.ok(frFrManifest, 'fr-fr manifest should exist');
// Compare the rendered manifest with the fixture, ignoring the timestamp
const normalizeTimestamp = (content: string) => content.replace(/<date>.*?<\/date>/, '<date>TIMESTAMP</date>');
assert.strictEqual(
normalizeTimestamp(frFrManifest.contents),
normalizeTimestamp(expectedContent),
'macOS fr-fr manifest should match the fixture (ignoring timestamp)'
);
});
test('should render Windows ADML with fr-fr locale', async () => {
const parsedPolicies = parsePolicies(policies);
const result = renderGP(mockProduct, parsedPolicies, frenchTranslations);
// Load the expected fixture file
const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'fr-fr', 'CodeOSS.adml');
const expectedContent = await fs.readFile(fixturePath, 'utf-8');
// Find the fr-fr ADML
const frFrAdml = result.adml.find(a => a.languageId === 'fr-fr');
assert.ok(frFrAdml, 'fr-fr ADML should exist');
// Compare the rendered ADML with the fixture
assert.strictEqual(frFrAdml.contents, expectedContent, 'Windows fr-fr ADML should match the fixture');
});
});
+683
View File
@@ -0,0 +1,683 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const render_js_1 = require("../policies/render.js");
const types_js_1 = require("../policies/types.js");
suite('Render Functions', () => {
suite('renderADMLString', () => {
test('should render ADML string without translations', () => {
const nlsString = {
value: 'Test description',
nlsKey: 'test.description'
};
const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString);
assert_1.default.strictEqual(result, '<string id="TestPrefix_test_description">Test description</string>');
});
test('should replace dots with underscores in nls key', () => {
const nlsString = {
value: 'Test value',
nlsKey: 'my.test.nls.key'
};
const result = (0, render_js_1.renderADMLString)('Prefix', 'testModule', nlsString);
assert_1.default.ok(result.includes('id="Prefix_my_test_nls_key"'));
});
test('should use translation when available', () => {
const nlsString = {
value: 'Original value',
nlsKey: 'test.key'
};
const translations = {
'testModule': {
'test.key': 'Translated value'
}
};
const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString, translations);
assert_1.default.ok(result.includes('>Translated value</string>'));
});
test('should fallback to original value when translation not found', () => {
const nlsString = {
value: 'Original value',
nlsKey: 'test.key'
};
const translations = {
'testModule': {
'other.key': 'Other translation'
}
};
const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString, translations);
assert_1.default.ok(result.includes('>Original value</string>'));
});
});
suite('renderProfileString', () => {
test('should render profile string without translations', () => {
const nlsString = {
value: 'Profile description',
nlsKey: 'profile.description'
};
const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString);
assert_1.default.strictEqual(result, 'Profile description');
});
test('should use translation when available', () => {
const nlsString = {
value: 'Original profile value',
nlsKey: 'profile.key'
};
const translations = {
'testModule': {
'profile.key': 'Translated profile value'
}
};
const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString, translations);
assert_1.default.strictEqual(result, 'Translated profile value');
});
test('should fallback to original value when translation not found', () => {
const nlsString = {
value: 'Original profile value',
nlsKey: 'profile.key'
};
const translations = {
'testModule': {
'other.key': 'Other translation'
}
};
const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString, translations);
assert_1.default.strictEqual(result, 'Original profile value');
});
});
suite('renderADMX', () => {
const mockCategory = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy = {
name: 'TestPolicy',
type: types_js_1.PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey) => [
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy">Test Policy</string>'],
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy</string></dict>'
};
test('should render ADMX with correct XML structure', () => {
const result = (0, render_js_1.renderADMX)('VSCode', ['1.85'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
assert_1.default.ok(result.includes('<policyDefinitions'));
assert_1.default.ok(result.includes('</policyDefinitions>'));
});
test('should include policy namespaces with regKey', () => {
const result = (0, render_js_1.renderADMX)('TestApp', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<target prefix="TestApp" namespace="Microsoft.Policies.TestApp"'));
});
test('should replace dots in versions with underscores', () => {
const result = (0, render_js_1.renderADMX)('VSCode', ['1.85.0', '1.90.1'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('Supported_1_85_0'));
assert_1.default.ok(result.includes('Supported_1_90_1'));
assert_1.default.ok(!result.includes('Supported_1.85.0'));
});
test('should include categories in correct structure', () => {
const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<categories>'));
assert_1.default.ok(result.includes('<category displayName="$(string.Application)" name="Application"'));
assert_1.default.ok(result.includes(`<category displayName="$(string.Category_${mockCategory.name.nlsKey})"`));
assert_1.default.ok(result.includes('</categories>'));
});
test('should include policies section', () => {
const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<policies>'));
assert_1.default.ok(result.includes('TestPolicy'));
assert_1.default.ok(result.includes('</policies>'));
});
test('should handle multiple versions', () => {
const result = (0, render_js_1.renderADMX)('VSCode', ['1.0', '1.5', '2.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('Supported_1_0'));
assert_1.default.ok(result.includes('Supported_1_5'));
assert_1.default.ok(result.includes('Supported_2_0'));
});
test('should handle multiple categories', () => {
const category1 = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
const category2 = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [category1, category2], [mockPolicy]);
assert_1.default.ok(result.includes('Category_cat1'));
assert_1.default.ok(result.includes('Category_cat2'));
});
test('should handle multiple policies', () => {
const policy2 = {
name: 'TestPolicy2',
type: types_js_1.PolicyType.String,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey) => [
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><string /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>'],
renderADMLPresentation: () => '<presentation id="TestPolicy2"/>',
renderProfile: () => ['<key>TestPolicy2</key>', '<string/>'],
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy2</string></dict>'
};
const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
assert_1.default.ok(result.includes('TestPolicy'));
assert_1.default.ok(result.includes('TestPolicy2'));
});
});
suite('renderADML', () => {
const mockCategory = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy = {
name: 'TestPolicy',
type: types_js_1.PolicyType.String,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: () => [],
renderADMLStrings: (translations) => [
`<string id="TestPolicy">Test Policy ${translations?.['testModule']?.['test.policy'] || 'Default'}</string>`
],
renderADMLPresentation: () => '<presentation id="TestPolicy"><textBox refId="TestPolicy"/></presentation>',
renderProfile: () => [],
renderProfileManifest: () => ''
};
test('should render ADML with correct XML structure', () => {
const result = (0, render_js_1.renderADML)('VS Code', ['1.85'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
assert_1.default.ok(result.includes('<policyDefinitionResources'));
assert_1.default.ok(result.includes('</policyDefinitionResources>'));
});
test('should include application name', () => {
const result = (0, render_js_1.renderADML)('My Application', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<string id="Application">My Application</string>'));
});
test('should include supported versions with escaped greater-than', () => {
const result = (0, render_js_1.renderADML)('VS Code', ['1.85', '1.90'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('VS Code &gt;= 1.85'));
assert_1.default.ok(result.includes('VS Code &gt;= 1.90'));
});
test('should include category strings', () => {
const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('Category_test_category'));
});
test('should include policy strings', () => {
const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('TestPolicy'));
assert_1.default.ok(result.includes('Test Policy Default'));
});
test('should include policy presentations', () => {
const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<presentationTable>'));
assert_1.default.ok(result.includes('<presentation id="TestPolicy">'));
assert_1.default.ok(result.includes('</presentationTable>'));
});
test('should pass translations to policy strings', () => {
const translations = {
'testModule': {
'test.policy': 'Translated'
}
};
const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy], translations);
assert_1.default.ok(result.includes('Test Policy Translated'));
});
test('should handle multiple categories', () => {
const category1 = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
const category2 = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [category1, category2], [mockPolicy]);
assert_1.default.ok(result.includes('Category_cat1'));
assert_1.default.ok(result.includes('Category_cat2'));
});
});
suite('renderProfileManifest', () => {
const mockCategory = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy = {
name: 'TestPolicy',
type: types_js_1.PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.0',
renderADMX: () => [],
renderADMLStrings: () => [],
renderADMLPresentation: () => '',
renderProfile: () => [],
renderProfileManifest: (translations) => `<dict>
<key>pfm_name</key>
<string>TestPolicy</string>
<key>pfm_description</key>
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
</dict>`
};
test('should render profile manifest with correct XML structure', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<?xml version="1.0" encoding="UTF-8"?>'));
assert_1.default.ok(result.includes('<!DOCTYPE plist PUBLIC'));
assert_1.default.ok(result.includes('<plist version="1.0">'));
assert_1.default.ok(result.includes('</plist>'));
});
test('should include app name', () => {
const result = (0, render_js_1.renderProfileManifest)('My App', 'com.example.myapp', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<string>My App Managed Settings</string>'));
assert_1.default.ok(result.includes('<string>My App</string>'));
});
test('should include bundle identifier', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<string>com.microsoft.vscode</string>'));
});
test('should include required payload fields', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('PayloadDescription'));
assert_1.default.ok(result.includes('PayloadDisplayName'));
assert_1.default.ok(result.includes('PayloadIdentifier'));
assert_1.default.ok(result.includes('PayloadType'));
assert_1.default.ok(result.includes('PayloadUUID'));
assert_1.default.ok(result.includes('PayloadVersion'));
assert_1.default.ok(result.includes('PayloadOrganization'));
});
test('should include policy manifests in subkeys', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_subkeys</key>'));
assert_1.default.ok(result.includes('TestPolicy'));
assert_1.default.ok(result.includes('Default Desc'));
});
test('should pass translations to policy manifests', () => {
const translations = {
'testModule': {
'test.desc': 'Translated Description'
}
};
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy], translations);
assert_1.default.ok(result.includes('Translated Description'));
});
test('should include VS Code specific URLs', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('https://code.visualstudio.com/'));
assert_1.default.ok(result.includes('https://code.visualstudio.com/docs/setup/enterprise'));
});
test('should include last modified date', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_last_modified</key>'));
assert_1.default.ok(result.includes('<date>'));
});
test('should mark manifest as unique', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_unique</key>'));
assert_1.default.ok(result.includes('<true/>'));
});
test('should handle multiple policies', () => {
const policy2 = {
...mockPolicy,
name: 'TestPolicy2',
renderProfileManifest: () => `<dict>
<key>pfm_name</key>
<string>TestPolicy2</string>
</dict>`
};
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
assert_1.default.ok(result.includes('TestPolicy'));
assert_1.default.ok(result.includes('TestPolicy2'));
});
test('should set format version to 1', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_format_version</key>'));
assert_1.default.ok(result.includes('<integer>1</integer>'));
});
test('should set interaction to combined', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_interaction</key>'));
assert_1.default.ok(result.includes('<string>combined</string>'));
});
test('should set platform to macOS', () => {
const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert_1.default.ok(result.includes('<key>pfm_platforms</key>'));
assert_1.default.ok(result.includes('<string>macOS</string>'));
});
});
suite('renderMacOSPolicy', () => {
const mockCategory = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy = {
name: 'TestPolicy',
type: types_js_1.PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.0',
renderADMX: () => [],
renderADMLStrings: () => [],
renderADMLPresentation: () => '',
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
renderProfileManifest: (translations) => `<dict>
<key>pfm_name</key>
<string>TestPolicy</string>
<key>pfm_description</key>
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
</dict>`
};
test('should render complete macOS policy profile', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []);
const expected = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>VS Code</string>
<key>PayloadIdentifier</key>
<string>com.microsoft.vscode.uuid</string>
<key>PayloadType</key>
<string>com.microsoft.vscode</string>
<key>PayloadUUID</key>
<string>uuid</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TestPolicy</key>
<true/>
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages VS Code. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>VS Code</string>
<key>PayloadIdentifier</key>
<string>com.microsoft.vscode</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>payload-uuid</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`;
assert_1.default.strictEqual(result.profile, expected);
});
test('should include en-us manifest by default', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []);
assert_1.default.strictEqual(result.manifests.length, 1);
assert_1.default.strictEqual(result.manifests[0].languageId, 'en-us');
assert_1.default.ok(result.manifests[0].contents.includes('VS Code Managed Settings'));
});
test('should include translations', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const translations = [
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.desc': 'Description Française' } } },
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.desc': 'Deutsche Beschreibung' } } }
];
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], translations);
assert_1.default.strictEqual(result.manifests.length, 3); // en-us + 2 translations
assert_1.default.strictEqual(result.manifests[0].languageId, 'en-us');
assert_1.default.strictEqual(result.manifests[1].languageId, 'fr-fr');
assert_1.default.strictEqual(result.manifests[2].languageId, 'de-de');
assert_1.default.ok(result.manifests[1].contents.includes('Description Française'));
assert_1.default.ok(result.manifests[2].contents.includes('Deutsche Beschreibung'));
});
test('should handle multiple policies with correct indentation', () => {
const policy2 = {
...mockPolicy,
name: 'TestPolicy2',
renderProfile: () => ['<key>TestPolicy2</key>', '<string>test value</string>']
};
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy, policy2], []);
assert_1.default.ok(result.profile.includes('<key>TestPolicy</key>'));
assert_1.default.ok(result.profile.includes('<true/>'));
assert_1.default.ok(result.profile.includes('<key>TestPolicy2</key>'));
assert_1.default.ok(result.profile.includes('<string>test value</string>'));
});
test('should use provided UUIDs in profile', () => {
const product = {
nameLong: 'My App',
darwinBundleIdentifier: 'com.example.app',
darwinProfilePayloadUUID: 'custom-payload-uuid',
darwinProfileUUID: 'custom-uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []);
assert_1.default.ok(result.profile.includes('<string>custom-payload-uuid</string>'));
assert_1.default.ok(result.profile.includes('<string>custom-uuid</string>'));
assert_1.default.ok(result.profile.includes('<string>com.example.app.custom-uuid</string>'));
});
test('should include enterprise documentation link', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []);
assert_1.default.ok(result.profile.includes('https://code.visualstudio.com/docs/setup/enterprise'));
});
test('should set TargetDeviceType to 5', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []);
assert_1.default.ok(result.profile.includes('<key>TargetDeviceType</key>'));
assert_1.default.ok(result.profile.includes('<integer>5</integer>'));
});
});
suite('renderGP', () => {
const mockCategory = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy = {
name: 'TestPolicy',
type: types_js_1.PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey) => [
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: (translations) => [
`<string id="TestPolicy">${translations?.['testModule']?.['test.policy'] || 'Test Policy'}</string>`
],
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
renderProfile: () => [],
renderProfileManifest: () => ''
};
test('should render complete GP with ADMX and ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.admx);
assert_1.default.ok(result.adml);
assert_1.default.ok(Array.isArray(result.adml));
});
test('should include regKey in ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'CustomRegKey'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.admx.includes('CustomRegKey'));
assert_1.default.ok(result.admx.includes('Software\\Policies\\Microsoft\\CustomRegKey'));
});
test('should include en-us ADML by default', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.strictEqual(result.adml.length, 1);
assert_1.default.strictEqual(result.adml[0].languageId, 'en-us');
assert_1.default.ok(result.adml[0].contents.includes('VS Code'));
});
test('should include translations in ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const translations = [
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.policy': 'Politique de test' } } },
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.policy': 'Testrichtlinie' } } }
];
const result = (0, render_js_1.renderGP)(product, [mockPolicy], translations);
assert_1.default.strictEqual(result.adml.length, 3); // en-us + 2 translations
assert_1.default.strictEqual(result.adml[0].languageId, 'en-us');
assert_1.default.strictEqual(result.adml[1].languageId, 'fr-fr');
assert_1.default.strictEqual(result.adml[2].languageId, 'de-de');
assert_1.default.ok(result.adml[1].contents.includes('Politique de test'));
assert_1.default.ok(result.adml[2].contents.includes('Testrichtlinie'));
});
test('should pass versions to ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.admx.includes('Supported_1_85'));
});
test('should pass versions to ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.adml[0].contents.includes('VS Code &gt;= 1.85'));
});
test('should pass categories to ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.admx.includes('test.category'));
});
test('should pass categories to ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.adml[0].contents.includes('Category_test_category'));
});
test('should handle multiple policies', () => {
const policy2 = {
...mockPolicy,
name: 'TestPolicy2',
renderADMX: (regKey) => [
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>']
};
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy, policy2], []);
assert_1.default.ok(result.admx.includes('TestPolicy'));
assert_1.default.ok(result.admx.includes('TestPolicy2'));
assert_1.default.ok(result.adml[0].contents.includes('TestPolicy'));
assert_1.default.ok(result.adml[0].contents.includes('TestPolicy2'));
});
test('should include app name in ADML', () => {
const product = {
nameLong: 'My Custom App',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok(result.adml[0].contents.includes('My Custom App'));
});
test('should return structured result with admx and adml properties', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = (0, render_js_1.renderGP)(product, [mockPolicy], []);
assert_1.default.ok('admx' in result);
assert_1.default.ok('adml' in result);
assert_1.default.strictEqual(typeof result.admx, 'string');
assert_1.default.ok(Array.isArray(result.adml));
});
});
});
//# sourceMappingURL=render.test.js.map
+827
View File
@@ -0,0 +1,827 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { renderADMLString, renderProfileString, renderADMX, renderADML, renderProfileManifest, renderMacOSPolicy, renderGP } from '../policies/render.js';
import { NlsString, LanguageTranslations, Category, Policy, PolicyType } from '../policies/types.js';
suite('Render Functions', () => {
suite('renderADMLString', () => {
test('should render ADML string without translations', () => {
const nlsString: NlsString = {
value: 'Test description',
nlsKey: 'test.description'
};
const result = renderADMLString('TestPrefix', 'testModule', nlsString);
assert.strictEqual(result, '<string id="TestPrefix_test_description">Test description</string>');
});
test('should replace dots with underscores in nls key', () => {
const nlsString: NlsString = {
value: 'Test value',
nlsKey: 'my.test.nls.key'
};
const result = renderADMLString('Prefix', 'testModule', nlsString);
assert.ok(result.includes('id="Prefix_my_test_nls_key"'));
});
test('should use translation when available', () => {
const nlsString: NlsString = {
value: 'Original value',
nlsKey: 'test.key'
};
const translations: LanguageTranslations = {
'testModule': {
'test.key': 'Translated value'
}
};
const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations);
assert.ok(result.includes('>Translated value</string>'));
});
test('should fallback to original value when translation not found', () => {
const nlsString: NlsString = {
value: 'Original value',
nlsKey: 'test.key'
};
const translations: LanguageTranslations = {
'testModule': {
'other.key': 'Other translation'
}
};
const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations);
assert.ok(result.includes('>Original value</string>'));
});
});
suite('renderProfileString', () => {
test('should render profile string without translations', () => {
const nlsString: NlsString = {
value: 'Profile description',
nlsKey: 'profile.description'
};
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString);
assert.strictEqual(result, 'Profile description');
});
test('should use translation when available', () => {
const nlsString: NlsString = {
value: 'Original profile value',
nlsKey: 'profile.key'
};
const translations: LanguageTranslations = {
'testModule': {
'profile.key': 'Translated profile value'
}
};
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations);
assert.strictEqual(result, 'Translated profile value');
});
test('should fallback to original value when translation not found', () => {
const nlsString: NlsString = {
value: 'Original profile value',
nlsKey: 'profile.key'
};
const translations: LanguageTranslations = {
'testModule': {
'other.key': 'Other translation'
}
};
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations);
assert.strictEqual(result, 'Original profile value');
});
});
suite('renderADMX', () => {
const mockCategory: Category = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy: Policy = {
name: 'TestPolicy',
type: PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey: string) => [
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy">Test Policy</string>'],
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy</string></dict>'
};
test('should render ADMX with correct XML structure', () => {
const result = renderADMX('VSCode', ['1.85'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
assert.ok(result.includes('<policyDefinitions'));
assert.ok(result.includes('</policyDefinitions>'));
});
test('should include policy namespaces with regKey', () => {
const result = renderADMX('TestApp', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<target prefix="TestApp" namespace="Microsoft.Policies.TestApp"'));
});
test('should replace dots in versions with underscores', () => {
const result = renderADMX('VSCode', ['1.85.0', '1.90.1'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('Supported_1_85_0'));
assert.ok(result.includes('Supported_1_90_1'));
assert.ok(!result.includes('Supported_1.85.0'));
});
test('should include categories in correct structure', () => {
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<categories>'));
assert.ok(result.includes('<category displayName="$(string.Application)" name="Application"'));
assert.ok(result.includes(`<category displayName="$(string.Category_${mockCategory.name.nlsKey})"`));
assert.ok(result.includes('</categories>'));
});
test('should include policies section', () => {
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<policies>'));
assert.ok(result.includes('TestPolicy'));
assert.ok(result.includes('</policies>'));
});
test('should handle multiple versions', () => {
const result = renderADMX('VSCode', ['1.0', '1.5', '2.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('Supported_1_0'));
assert.ok(result.includes('Supported_1_5'));
assert.ok(result.includes('Supported_2_0'));
});
test('should handle multiple categories', () => {
const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
const result = renderADMX('VSCode', ['1.0'], [category1, category2], [mockPolicy]);
assert.ok(result.includes('Category_cat1'));
assert.ok(result.includes('Category_cat2'));
});
test('should handle multiple policies', () => {
const policy2: Policy = {
name: 'TestPolicy2',
type: PolicyType.String,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey: string) => [
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><string /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>'],
renderADMLPresentation: () => '<presentation id="TestPolicy2"/>',
renderProfile: () => ['<key>TestPolicy2</key>', '<string/>'],
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy2</string></dict>'
};
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
assert.ok(result.includes('TestPolicy'));
assert.ok(result.includes('TestPolicy2'));
});
});
suite('renderADML', () => {
const mockCategory: Category = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy: Policy = {
name: 'TestPolicy',
type: PolicyType.String,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: () => [],
renderADMLStrings: (translations?: LanguageTranslations) => [
`<string id="TestPolicy">Test Policy ${translations?.['testModule']?.['test.policy'] || 'Default'}</string>`
],
renderADMLPresentation: () => '<presentation id="TestPolicy"><textBox refId="TestPolicy"/></presentation>',
renderProfile: () => [],
renderProfileManifest: () => ''
};
test('should render ADML with correct XML structure', () => {
const result = renderADML('VS Code', ['1.85'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
assert.ok(result.includes('<policyDefinitionResources'));
assert.ok(result.includes('</policyDefinitionResources>'));
});
test('should include application name', () => {
const result = renderADML('My Application', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<string id="Application">My Application</string>'));
});
test('should include supported versions with escaped greater-than', () => {
const result = renderADML('VS Code', ['1.85', '1.90'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('VS Code &gt;= 1.85'));
assert.ok(result.includes('VS Code &gt;= 1.90'));
});
test('should include category strings', () => {
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('Category_test_category'));
});
test('should include policy strings', () => {
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('TestPolicy'));
assert.ok(result.includes('Test Policy Default'));
});
test('should include policy presentations', () => {
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<presentationTable>'));
assert.ok(result.includes('<presentation id="TestPolicy">'));
assert.ok(result.includes('</presentationTable>'));
});
test('should pass translations to policy strings', () => {
const translations: LanguageTranslations = {
'testModule': {
'test.policy': 'Translated'
}
};
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy], translations);
assert.ok(result.includes('Test Policy Translated'));
});
test('should handle multiple categories', () => {
const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
const result = renderADML('VS Code', ['1.0'], [category1, category2], [mockPolicy]);
assert.ok(result.includes('Category_cat1'));
assert.ok(result.includes('Category_cat2'));
});
});
suite('renderProfileManifest', () => {
const mockCategory: Category = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy: Policy = {
name: 'TestPolicy',
type: PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.0',
renderADMX: () => [],
renderADMLStrings: () => [],
renderADMLPresentation: () => '',
renderProfile: () => [],
renderProfileManifest: (translations?: LanguageTranslations) => `<dict>
<key>pfm_name</key>
<string>TestPolicy</string>
<key>pfm_description</key>
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
</dict>`
};
test('should render profile manifest with correct XML structure', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<?xml version="1.0" encoding="UTF-8"?>'));
assert.ok(result.includes('<!DOCTYPE plist PUBLIC'));
assert.ok(result.includes('<plist version="1.0">'));
assert.ok(result.includes('</plist>'));
});
test('should include app name', () => {
const result = renderProfileManifest('My App', 'com.example.myapp', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<string>My App Managed Settings</string>'));
assert.ok(result.includes('<string>My App</string>'));
});
test('should include bundle identifier', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<string>com.microsoft.vscode</string>'));
});
test('should include required payload fields', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('PayloadDescription'));
assert.ok(result.includes('PayloadDisplayName'));
assert.ok(result.includes('PayloadIdentifier'));
assert.ok(result.includes('PayloadType'));
assert.ok(result.includes('PayloadUUID'));
assert.ok(result.includes('PayloadVersion'));
assert.ok(result.includes('PayloadOrganization'));
});
test('should include policy manifests in subkeys', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_subkeys</key>'));
assert.ok(result.includes('TestPolicy'));
assert.ok(result.includes('Default Desc'));
});
test('should pass translations to policy manifests', () => {
const translations: LanguageTranslations = {
'testModule': {
'test.desc': 'Translated Description'
}
};
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy], translations);
assert.ok(result.includes('Translated Description'));
});
test('should include VS Code specific URLs', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('https://code.visualstudio.com/'));
assert.ok(result.includes('https://code.visualstudio.com/docs/setup/enterprise'));
});
test('should include last modified date', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_last_modified</key>'));
assert.ok(result.includes('<date>'));
});
test('should mark manifest as unique', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_unique</key>'));
assert.ok(result.includes('<true/>'));
});
test('should handle multiple policies', () => {
const policy2: Policy = {
...mockPolicy,
name: 'TestPolicy2',
renderProfileManifest: () => `<dict>
<key>pfm_name</key>
<string>TestPolicy2</string>
</dict>`
};
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
assert.ok(result.includes('TestPolicy'));
assert.ok(result.includes('TestPolicy2'));
});
test('should set format version to 1', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_format_version</key>'));
assert.ok(result.includes('<integer>1</integer>'));
});
test('should set interaction to combined', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_interaction</key>'));
assert.ok(result.includes('<string>combined</string>'));
});
test('should set platform to macOS', () => {
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
assert.ok(result.includes('<key>pfm_platforms</key>'));
assert.ok(result.includes('<string>macOS</string>'));
});
});
suite('renderMacOSPolicy', () => {
const mockCategory: Category = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy: Policy = {
name: 'TestPolicy',
type: PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.0',
renderADMX: () => [],
renderADMLStrings: () => [],
renderADMLPresentation: () => '',
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
renderProfileManifest: (translations?: LanguageTranslations) => `<dict>
<key>pfm_name</key>
<string>TestPolicy</string>
<key>pfm_description</key>
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
</dict>`
};
test('should render complete macOS policy profile', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy], []);
const expected = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>PayloadDisplayName</key>
<string>VS Code</string>
<key>PayloadIdentifier</key>
<string>com.microsoft.vscode.uuid</string>
<key>PayloadType</key>
<string>com.microsoft.vscode</string>
<key>PayloadUUID</key>
<string>uuid</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TestPolicy</key>
<true/>
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile manages VS Code. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
<key>PayloadDisplayName</key>
<string>VS Code</string>
<key>PayloadIdentifier</key>
<string>com.microsoft.vscode</string>
<key>PayloadOrganization</key>
<string>Microsoft</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>payload-uuid</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>TargetDeviceType</key>
<integer>5</integer>
</dict>
</plist>`;
assert.strictEqual(result.profile, expected);
});
test('should include en-us manifest by default', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy], []);
assert.strictEqual(result.manifests.length, 1);
assert.strictEqual(result.manifests[0].languageId, 'en-us');
assert.ok(result.manifests[0].contents.includes('VS Code Managed Settings'));
});
test('should include translations', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const translations = [
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.desc': 'Description Française' } } },
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.desc': 'Deutsche Beschreibung' } } }
];
const result = renderMacOSPolicy(product, [mockPolicy], translations);
assert.strictEqual(result.manifests.length, 3); // en-us + 2 translations
assert.strictEqual(result.manifests[0].languageId, 'en-us');
assert.strictEqual(result.manifests[1].languageId, 'fr-fr');
assert.strictEqual(result.manifests[2].languageId, 'de-de');
assert.ok(result.manifests[1].contents.includes('Description Française'));
assert.ok(result.manifests[2].contents.includes('Deutsche Beschreibung'));
});
test('should handle multiple policies with correct indentation', () => {
const policy2: Policy = {
...mockPolicy,
name: 'TestPolicy2',
renderProfile: () => ['<key>TestPolicy2</key>', '<string>test value</string>']
};
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy, policy2], []);
assert.ok(result.profile.includes('<key>TestPolicy</key>'));
assert.ok(result.profile.includes('<true/>'));
assert.ok(result.profile.includes('<key>TestPolicy2</key>'));
assert.ok(result.profile.includes('<string>test value</string>'));
});
test('should use provided UUIDs in profile', () => {
const product = {
nameLong: 'My App',
darwinBundleIdentifier: 'com.example.app',
darwinProfilePayloadUUID: 'custom-payload-uuid',
darwinProfileUUID: 'custom-uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy], []);
assert.ok(result.profile.includes('<string>custom-payload-uuid</string>'));
assert.ok(result.profile.includes('<string>custom-uuid</string>'));
assert.ok(result.profile.includes('<string>com.example.app.custom-uuid</string>'));
});
test('should include enterprise documentation link', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy], []);
assert.ok(result.profile.includes('https://code.visualstudio.com/docs/setup/enterprise'));
});
test('should set TargetDeviceType to 5', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderMacOSPolicy(product, [mockPolicy], []);
assert.ok(result.profile.includes('<key>TargetDeviceType</key>'));
assert.ok(result.profile.includes('<integer>5</integer>'));
});
});
suite('renderGP', () => {
const mockCategory: Category = {
moduleName: 'testModule',
name: { value: 'Test Category', nlsKey: 'test.category' }
};
const mockPolicy: Policy = {
name: 'TestPolicy',
type: PolicyType.Boolean,
category: mockCategory,
minimumVersion: '1.85',
renderADMX: (regKey: string) => [
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: (translations?: LanguageTranslations) => [
`<string id="TestPolicy">${translations?.['testModule']?.['test.policy'] || 'Test Policy'}</string>`
],
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
renderProfile: () => [],
renderProfileManifest: () => ''
};
test('should render complete GP with ADMX and ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.admx);
assert.ok(result.adml);
assert.ok(Array.isArray(result.adml));
});
test('should include regKey in ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'CustomRegKey'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.admx.includes('CustomRegKey'));
assert.ok(result.admx.includes('Software\\Policies\\Microsoft\\CustomRegKey'));
});
test('should include en-us ADML by default', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.strictEqual(result.adml.length, 1);
assert.strictEqual(result.adml[0].languageId, 'en-us');
assert.ok(result.adml[0].contents.includes('VS Code'));
});
test('should include translations in ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const translations = [
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.policy': 'Politique de test' } } },
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.policy': 'Testrichtlinie' } } }
];
const result = renderGP(product, [mockPolicy], translations);
assert.strictEqual(result.adml.length, 3); // en-us + 2 translations
assert.strictEqual(result.adml[0].languageId, 'en-us');
assert.strictEqual(result.adml[1].languageId, 'fr-fr');
assert.strictEqual(result.adml[2].languageId, 'de-de');
assert.ok(result.adml[1].contents.includes('Politique de test'));
assert.ok(result.adml[2].contents.includes('Testrichtlinie'));
});
test('should pass versions to ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.admx.includes('Supported_1_85'));
});
test('should pass versions to ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.adml[0].contents.includes('VS Code &gt;= 1.85'));
});
test('should pass categories to ADMX', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.admx.includes('test.category'));
});
test('should pass categories to ADML', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.adml[0].contents.includes('Category_test_category'));
});
test('should handle multiple policies', () => {
const policy2: Policy = {
...mockPolicy,
name: 'TestPolicy2',
renderADMX: (regKey: string) => [
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
` <enabledValue><decimal value="1" /></enabledValue>`,
`</policy>`
],
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>']
};
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy, policy2], []);
assert.ok(result.admx.includes('TestPolicy'));
assert.ok(result.admx.includes('TestPolicy2'));
assert.ok(result.adml[0].contents.includes('TestPolicy'));
assert.ok(result.adml[0].contents.includes('TestPolicy2'));
});
test('should include app name in ADML', () => {
const product = {
nameLong: 'My Custom App',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok(result.adml[0].contents.includes('My Custom App'));
});
test('should return structured result with admx and adml properties', () => {
const product = {
nameLong: 'VS Code',
darwinBundleIdentifier: 'com.microsoft.vscode',
darwinProfilePayloadUUID: 'payload-uuid',
darwinProfileUUID: 'uuid',
win32RegValueName: 'VSCode'
};
const result = renderGP(product, [mockPolicy], []);
assert.ok('admx' in result);
assert.ok('adml' in result);
assert.strictEqual(typeof result.admx, 'string');
assert.ok(Array.isArray(result.adml));
});
});
});
+136
View File
@@ -0,0 +1,136 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const stringEnumPolicy_js_1 = require("../policies/stringEnumPolicy.js");
const types_js_1 = require("../policies/types.js");
suite('StringEnumPolicy', () => {
const mockCategory = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy = {
key: 'test.stringenum.policy',
name: 'TestStringEnumPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'string',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' },
enumDescriptions: [
{ key: 'test.option.one', value: 'Option One' },
{ key: 'test.option.two', value: 'Option Two' },
{ key: 'test.option.three', value: 'Option Three' }
]
},
enum: ['auto', 'manual', 'disabled']
};
test('should create StringEnumPolicy from factory method', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
assert_1.default.strictEqual(policy.name, 'TestStringEnumPolicy');
assert_1.default.strictEqual(policy.minimumVersion, '1.0');
assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value);
assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.StringEnum);
});
test('should render ADMX elements correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admx = policy.renderADMX('TestKey');
assert_1.default.deepStrictEqual(admx, [
'<policy name="TestStringEnumPolicy" class="Both" displayName="$(string.TestStringEnumPolicy)" explainText="$(string.TestStringEnumPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestStringEnumPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<enum id="TestStringEnumPolicy" valueName="TestStringEnumPolicy">',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.one)"><value><string>auto</string></value></item>',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.two)"><value><string>manual</string></value></item>',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.three)"><value><string>disabled</string></value></item>',
'</enum>',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestStringEnumPolicy">TestStringEnumPolicy</string>',
'<string id="TestStringEnumPolicy_test_policy_description">Test policy description</string>',
'<string id="TestStringEnumPolicy_test_option_one">Option One</string>',
'<string id="TestStringEnumPolicy_test_option_two">Option Two</string>',
'<string id="TestStringEnumPolicy_test_option_three">Option Three</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated description',
'test.option.one': 'Translated Option One',
'test.option.two': 'Translated Option Two'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestStringEnumPolicy">TestStringEnumPolicy</string>',
'<string id="TestStringEnumPolicy_test_policy_description">Translated description</string>',
'<string id="TestStringEnumPolicy_test_option_one">Translated Option One</string>',
'<string id="TestStringEnumPolicy_test_option_two">Translated Option Two</string>',
'<string id="TestStringEnumPolicy_test_option_three">Option Three</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const presentation = policy.renderADMLPresentation();
assert_1.default.strictEqual(presentation, '<presentation id="TestStringEnumPolicy"><dropdownList refId="TestStringEnumPolicy" /></presentation>');
});
test('should render profile value correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profileValue = policy.renderProfileValue();
assert_1.default.strictEqual(profileValue, '<string>auto</string>');
});
test('should render profile correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profile = policy.renderProfile();
assert_1.default.strictEqual(profile.length, 2);
assert_1.default.strictEqual(profile[0], '<key>TestStringEnumPolicy</key>');
assert_1.default.strictEqual(profile[1], '<string>auto</string>');
});
test('should render profile manifest value correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>');
});
test('should render profile manifest value with translations', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>');
});
test('should render profile manifest correctly', () => {
const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifest = policy.renderProfileManifest();
assert_1.default.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>\n</dict>');
});
});
//# sourceMappingURL=stringEnumPolicy.test.js.map
+174
View File
@@ -0,0 +1,174 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { StringEnumPolicy } from '../policies/stringEnumPolicy.js';
import { LanguageTranslations, PolicyType } from '../policies/types.js';
import { CategoryDto, PolicyDto } from '../policies/policyDto.js';
suite('StringEnumPolicy', () => {
const mockCategory: CategoryDto = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy: PolicyDto = {
key: 'test.stringenum.policy',
name: 'TestStringEnumPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'string',
localization: {
description: { key: 'test.policy.description', value: 'Test policy description' },
enumDescriptions: [
{ key: 'test.option.one', value: 'Option One' },
{ key: 'test.option.two', value: 'Option Two' },
{ key: 'test.option.three', value: 'Option Three' }
]
},
enum: ['auto', 'manual', 'disabled']
};
test('should create StringEnumPolicy from factory method', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
assert.strictEqual(policy.name, 'TestStringEnumPolicy');
assert.strictEqual(policy.minimumVersion, '1.0');
assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert.strictEqual(policy.category.name.value, mockCategory.name.value);
assert.strictEqual(policy.type, PolicyType.StringEnum);
});
test('should render ADMX elements correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admx = policy.renderADMX('TestKey');
assert.deepStrictEqual(admx, [
'<policy name="TestStringEnumPolicy" class="Both" displayName="$(string.TestStringEnumPolicy)" explainText="$(string.TestStringEnumPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestStringEnumPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<enum id="TestStringEnumPolicy" valueName="TestStringEnumPolicy">',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.one)"><value><string>auto</string></value></item>',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.two)"><value><string>manual</string></value></item>',
'\t<item displayName="$(string.TestStringEnumPolicy_test.option.three)"><value><string>disabled</string></value></item>',
'</enum>',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert.deepStrictEqual(admlStrings, [
'<string id="TestStringEnumPolicy">TestStringEnumPolicy</string>',
'<string id="TestStringEnumPolicy_test_policy_description">Test policy description</string>',
'<string id="TestStringEnumPolicy_test_option_one">Option One</string>',
'<string id="TestStringEnumPolicy_test_option_two">Option Two</string>',
'<string id="TestStringEnumPolicy_test_option_three">Option Three</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated description',
'test.option.one': 'Translated Option One',
'test.option.two': 'Translated Option Two'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert.deepStrictEqual(admlStrings, [
'<string id="TestStringEnumPolicy">TestStringEnumPolicy</string>',
'<string id="TestStringEnumPolicy_test_policy_description">Translated description</string>',
'<string id="TestStringEnumPolicy_test_option_one">Translated Option One</string>',
'<string id="TestStringEnumPolicy_test_option_two">Translated Option Two</string>',
'<string id="TestStringEnumPolicy_test_option_three">Option Three</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const presentation = policy.renderADMLPresentation();
assert.strictEqual(presentation, '<presentation id="TestStringEnumPolicy"><dropdownList refId="TestStringEnumPolicy" /></presentation>');
});
test('should render profile value correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profileValue = policy.renderProfileValue();
assert.strictEqual(profileValue, '<string>auto</string>');
});
test('should render profile correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profile = policy.renderProfile();
assert.strictEqual(profile.length, 2);
assert.strictEqual(profile[0], '<key>TestStringEnumPolicy</key>');
assert.strictEqual(profile[1], '<string>auto</string>');
});
test('should render profile manifest value correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>');
});
test('should render profile manifest value with translations', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>');
});
test('should render profile manifest correctly', () => {
const policy = StringEnumPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifest = policy.renderProfileManifest();
assert.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string>auto</string>\n<key>pfm_description</key>\n<string>Test policy description</string>\n<key>pfm_name</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_title</key>\n<string>TestStringEnumPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n<key>pfm_range_list</key>\n<array>\n\t<string>auto</string>\n\t<string>manual</string>\n\t<string>disabled</string>\n</array>\n</dict>');
});
});
+119
View File
@@ -0,0 +1,119 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const assert_1 = __importDefault(require("assert"));
const stringPolicy_js_1 = require("../policies/stringPolicy.js");
const types_js_1 = require("../policies/types.js");
suite('StringPolicy', () => {
const mockCategory = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy = {
key: 'test.string.policy',
name: 'TestStringPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'string',
default: '',
localization: {
description: { key: 'test.policy.description', value: 'Test string policy description' }
}
};
test('should create StringPolicy from factory method', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
assert_1.default.strictEqual(policy.name, 'TestStringPolicy');
assert_1.default.strictEqual(policy.minimumVersion, '1.0');
assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value);
assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.String);
});
test('should render ADMX elements correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admx = policy.renderADMX('TestKey');
assert_1.default.deepStrictEqual(admx, [
'<policy name="TestStringPolicy" class="Both" displayName="$(string.TestStringPolicy)" explainText="$(string.TestStringPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestStringPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<text id="TestStringPolicy" valueName="TestStringPolicy" required="true" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestStringPolicy">TestStringPolicy</string>',
'<string id="TestStringPolicy_test_policy_description">Test string policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert_1.default.deepStrictEqual(admlStrings, [
'<string id="TestStringPolicy">TestStringPolicy</string>',
'<string id="TestStringPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const presentation = policy.renderADMLPresentation();
assert_1.default.strictEqual(presentation, '<presentation id="TestStringPolicy"><textBox refId="TestStringPolicy"><label>TestStringPolicy:</label></textBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profileValue = policy.renderProfileValue();
assert_1.default.strictEqual(profileValue, '<string></string>');
});
test('should render profile correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const profile = policy.renderProfile();
assert_1.default.strictEqual(profile.length, 2);
assert_1.default.strictEqual(profile[0], '<key>TestStringPolicy</key>');
assert_1.default.strictEqual(profile[1], '<string></string>');
});
test('should render profile manifest value correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test string policy description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>');
});
test('should render profile manifest value with translations', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const translations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert_1.default.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>');
});
test('should render profile manifest correctly', () => {
const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy);
assert_1.default.ok(policy);
const manifest = policy.renderProfileManifest();
assert_1.default.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test string policy description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n</dict>');
});
});
//# sourceMappingURL=stringPolicy.test.js.map
+157
View File
@@ -0,0 +1,157 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert from 'assert';
import { StringPolicy } from '../policies/stringPolicy.js';
import { LanguageTranslations, PolicyType } from '../policies/types.js';
import { CategoryDto, PolicyDto } from '../policies/policyDto.js';
suite('StringPolicy', () => {
const mockCategory: CategoryDto = {
key: 'test.category',
name: { value: 'Category1', key: 'test.category' },
};
const mockPolicy: PolicyDto = {
key: 'test.string.policy',
name: 'TestStringPolicy',
category: 'Category1',
minimumVersion: '1.0',
type: 'string',
default: '',
localization: {
description: { key: 'test.policy.description', value: 'Test string policy description' }
}
};
test('should create StringPolicy from factory method', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
assert.strictEqual(policy.name, 'TestStringPolicy');
assert.strictEqual(policy.minimumVersion, '1.0');
assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key);
assert.strictEqual(policy.category.name.value, mockCategory.name.value);
assert.strictEqual(policy.type, PolicyType.String);
});
test('should render ADMX elements correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admx = policy.renderADMX('TestKey');
assert.deepStrictEqual(admx, [
'<policy name="TestStringPolicy" class="Both" displayName="$(string.TestStringPolicy)" explainText="$(string.TestStringPolicy_test_policy_description)" key="Software\\Policies\\Microsoft\\TestKey" presentation="$(presentation.TestStringPolicy)">',
'\t<parentCategory ref="test.category" />',
'\t<supportedOn ref="Supported_1_0" />',
'\t<elements>',
'<text id="TestStringPolicy" valueName="TestStringPolicy" required="true" />',
'\t</elements>',
'</policy>'
]);
});
test('should render ADML strings correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const admlStrings = policy.renderADMLStrings();
assert.deepStrictEqual(admlStrings, [
'<string id="TestStringPolicy">TestStringPolicy</string>',
'<string id="TestStringPolicy_test_policy_description">Test string policy description</string>'
]);
});
test('should render ADML strings with translations', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated description'
}
};
const admlStrings = policy.renderADMLStrings(translations);
assert.deepStrictEqual(admlStrings, [
'<string id="TestStringPolicy">TestStringPolicy</string>',
'<string id="TestStringPolicy_test_policy_description">Translated description</string>'
]);
});
test('should render ADML presentation correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const presentation = policy.renderADMLPresentation();
assert.strictEqual(presentation, '<presentation id="TestStringPolicy"><textBox refId="TestStringPolicy"><label>TestStringPolicy:</label></textBox></presentation>');
});
test('should render profile value correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profileValue = policy.renderProfileValue();
assert.strictEqual(profileValue, '<string></string>');
});
test('should render profile correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const profile = policy.renderProfile();
assert.strictEqual(profile.length, 2);
assert.strictEqual(profile[0], '<key>TestStringPolicy</key>');
assert.strictEqual(profile[1], '<string></string>');
});
test('should render profile manifest value correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifestValue = policy.renderProfileManifestValue();
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test string policy description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>');
});
test('should render profile manifest value with translations', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const translations: LanguageTranslations = {
'': {
'test.policy.description': 'Translated manifest description'
}
};
const manifestValue = policy.renderProfileManifestValue(translations);
assert.strictEqual(manifestValue, '<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Translated manifest description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>');
});
test('should render profile manifest correctly', () => {
const policy = StringPolicy.from(mockCategory, mockPolicy);
assert.ok(policy);
const manifest = policy.renderProfileManifest();
assert.strictEqual(manifest, '<dict>\n<key>pfm_default</key>\n<string></string>\n<key>pfm_description</key>\n<string>Test string policy description</string>\n<key>pfm_name</key>\n<string>TestStringPolicy</string>\n<key>pfm_title</key>\n<string>TestStringPolicy</string>\n<key>pfm_type</key>\n<string>string</string>\n</dict>');
});
});
+2 -1
View File
@@ -69,7 +69,8 @@
"build-ts": "cd .. && npx tsgo --project build/tsconfig.build.json",
"compile": "npm run build-ts",
"watch": "npm run build-ts -- --watch",
"npmCheckJs": "npm run build-ts -- --noEmit"
"npmCheckJs": "npm run build-ts -- --noEmit",
"test": "npx mocha --ui tdd 'lib/**/*.test.js'"
},
"optionalDependencies": {
"tree-sitter-typescript": "^0.23.2",