@forge/manifest 12.0.0 → 12.1.0-experimental-8b78d46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,9 +28,9 @@ class PermissionsValidator {
28
28
  remotesHasValidEntryForKey(remoteMap, key) {
29
29
  return (remoteMap !== undefined &&
30
30
  remoteMap.has(key) &&
31
- (remoteMap.get(key) === null || this.isValidURL(remoteMap.get(key))));
31
+ (remoteMap.get(key) === null || this.isValidURL(remoteMap.get(key), false)));
32
32
  }
33
- isValidURL(inputURL) {
33
+ isValidURL(inputURL, allowGlobalUrl) {
34
34
  const protocolRegex = /^(.*?:\/\/)/;
35
35
  const validURI = /^(\*\.)?[.a-zA-Z0-9_\-\/:~#%?=&]+$/;
36
36
  const allowedProtocols = ['https:', 'wss:'];
@@ -38,8 +38,8 @@ class PermissionsValidator {
38
38
  if (inputURL.length > MAX_URL_LENGTH) {
39
39
  return false;
40
40
  }
41
- if (inputURL === '*') {
42
- return true;
41
+ if (inputURL === egress_types_1.GLOBAL_URL) {
42
+ return allowGlobalUrl;
43
43
  }
44
44
  const customURLSchemeRegex = /^[a-zA-Z]+:(\\\\)?/;
45
45
  if (customURLSchemeRegex.test(inputURL) &&
@@ -70,6 +70,18 @@ class PermissionsValidator {
70
70
  ];
71
71
  return BASE_64_HASH_PATTERNS.some((pattern) => pattern.test(cspString));
72
72
  }
73
+ hasPathComponent(url) {
74
+ try {
75
+ const protocolRegex = /^(.*?:\/\/)/;
76
+ const urlWithProtocol = protocolRegex.test(url) ? url : `https://${url}`;
77
+ const parsedUrl = new url_1.URL(urlWithProtocol);
78
+ const pathname = parsedUrl.pathname;
79
+ return pathname.length > 0 && pathname !== '/';
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
73
85
  addValidationErrors(result, element, values, manifest) {
74
86
  values.forEach((value) => {
75
87
  result.push({
@@ -81,7 +93,7 @@ class PermissionsValidator {
81
93
  });
82
94
  }
83
95
  validateExternalPermissionURLs(result, extPermType, perms, manifest) {
84
- const invalidPerms = perms?.filter((key) => !this.isValidURL(key));
96
+ const invalidPerms = perms?.filter((key) => !this.isValidURL(key, true));
85
97
  if (invalidPerms?.length) {
86
98
  this.addValidationErrors(result, extPermType, invalidPerms, manifest);
87
99
  }
@@ -115,6 +127,19 @@ class PermissionsValidator {
115
127
  });
116
128
  }
117
129
  }
130
+ if (extPermType === 'external.fetch.backend') {
131
+ const urlsWithPaths = perms?.filter((key) => this.hasPathComponent(key));
132
+ if (urlsWithPaths?.length) {
133
+ urlsWithPaths.forEach((url) => {
134
+ result.push({
135
+ message: text_1.errors.permissions.backendEgressPathIgnored(url),
136
+ reference: text_1.References.Permissions,
137
+ level: 'warning',
138
+ ...(0, utils_1.findPosition)(url, manifest.yamlContentByLine)
139
+ });
140
+ });
141
+ }
142
+ }
118
143
  }
119
144
  async validate(manifest) {
120
145
  if (!manifest || !manifest.typedContent || !manifest.typedContent.permissions) {
@@ -186,7 +211,7 @@ class PermissionsValidator {
186
211
  }
187
212
  ];
188
213
  mapping.forEach((item) => this.validateExternalPermissionURLs(errors, item.element, item.perms, manifest));
189
- const { fetch: originalFetch, ...restOfExternalPermissions } = manifest.typedContent.permissions.external || {};
214
+ const { fetch: originalFetch, configurable: _configurable, ...restOfExternalPermissions } = manifest.typedContent.permissions.external || {};
190
215
  Object.entries(originalFetch || {}).forEach(([key, values]) => {
191
216
  if (values.some((value) => typeof value === 'string')) {
192
217
  errors.push({
@@ -215,24 +240,14 @@ class PermissionsValidator {
215
240
  });
216
241
  const remoteMap = manifest.typedContent.remotes?.reduce((prev, item) => {
217
242
  if ((0, features_1.configurableRemotesEnabled)()) {
218
- if (typeof item.configurable !== 'undefined') {
219
- if (typeof item.configurable.default !== 'undefined') {
220
- const baseUrl = item.configurable.default;
221
- return prev.set(item.key, baseUrl);
222
- }
223
- else {
224
- return prev.set(item.key, null);
225
- }
243
+ if (item.baseUrl) {
244
+ const baseUrl = typeof item.baseUrl === 'string' ? item.baseUrl : item.baseUrl.default;
245
+ return prev.set(item.key, baseUrl);
226
246
  }
227
- else {
228
- if (typeof item.baseUrl !== 'undefined') {
229
- const baseUrl = typeof item.baseUrl === 'string' ? item.baseUrl : item.baseUrl.default;
230
- return prev.set(item.key, baseUrl);
231
- }
232
- else {
233
- return prev;
234
- }
247
+ if (!item.baseUrl && item.configurable) {
248
+ return prev.set(item.key, null);
235
249
  }
250
+ return prev;
236
251
  }
237
252
  else {
238
253
  if (item.baseUrl !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"remotes-is-configurable-validator.d.ts","sourceRoot":"","sources":["../../src/validators/remotes-is-configurable-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAKrF,qBAAa,kCACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;YAI3E,WAAW;IAiCnB,WAAW,CACf,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IAgE9C,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CAOrD"}
1
+ {"version":3,"file":"remotes-is-configurable-validator.d.ts","sourceRoot":"","sources":["../../src/validators/remotes-is-configurable-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAKrF,qBAAa,kCACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;YAI3E,WAAW;IAiCnB,WAAW,CACf,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;IA+B9C,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CAOrD"}
@@ -38,43 +38,14 @@ class RemotesIsUserConfigurableValidator {
38
38
  }
39
39
  const remotes = manifest.typedContent.remotes;
40
40
  const validationErrors = [];
41
- const configurableRemotesAllowed = manifest.typedContent.permissions?.configurable?.enabled ?? false;
42
41
  remotes?.forEach((remote) => {
43
- if (!configurableRemotesAllowed) {
44
- if (remote.configurable !== undefined) {
45
- validationErrors.push({
46
- message: text_1.errors.modules.remote.userConfigurationPermissionsMismatch(remote.key),
47
- reference: text_1.References.App,
48
- level: 'error',
49
- ...(0, utils_1.findPosition)(remote.key, manifest.yamlContentByLine)
50
- });
51
- }
52
- if (remote.configurable === undefined && remote.baseUrl === undefined) {
53
- validationErrors.push({
54
- message: text_1.errors.modules.remote.baseUrlNotPresent(remote.key),
55
- reference: text_1.References.App,
56
- level: 'error',
57
- ...(0, utils_1.findPosition)(remote.key, manifest.yamlContentByLine)
58
- });
59
- }
60
- }
61
- else {
62
- if (remote.configurable === undefined && remote.baseUrl === undefined) {
63
- validationErrors.push({
64
- message: text_1.errors.modules.remote.neitherBaseUrlNorUserConfigurationPresent(remote.key),
65
- reference: text_1.References.App,
66
- level: 'error',
67
- ...(0, utils_1.findPosition)(remote.key, manifest.yamlContentByLine)
68
- });
69
- }
70
- else if (remote.configurable !== undefined && remote.baseUrl !== undefined) {
71
- validationErrors.push({
72
- message: text_1.errors.modules.remote.bothBaseUrlAndUserConfigurationPresent(remote.key),
73
- reference: text_1.References.App,
74
- level: 'error',
75
- ...(0, utils_1.findPosition)(remote.key, manifest.yamlContentByLine)
76
- });
77
- }
42
+ if (remote.configurable === undefined && remote.baseUrl === undefined) {
43
+ validationErrors.push({
44
+ message: text_1.errors.modules.remote.neitherBaseUrlNorUserConfigurationPresent(remote.key),
45
+ reference: text_1.References.App,
46
+ level: 'error',
47
+ ...(0, utils_1.findPosition)(remote.key, manifest.yamlContentByLine)
48
+ });
78
49
  }
79
50
  });
80
51
  return {
@@ -0,0 +1,7 @@
1
+ import { ValidatorInterface } from './validator-interface';
2
+ import { ManifestObject, ManifestValidationResult } from '../types';
3
+ import { ManifestSchema } from '../schema/manifest';
4
+ export declare class TwgPreviewScopesValidator implements ValidatorInterface<ManifestObject<ManifestSchema> | undefined, ManifestSchema> {
5
+ validate(manifest: ManifestObject<ManifestSchema> | undefined): Promise<ManifestValidationResult<ManifestSchema>>;
6
+ }
7
+ //# sourceMappingURL=twg-preview-scopes-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twg-preview-scopes-validator.d.ts","sourceRoot":"","sources":["../../src/validators/twg-preview-scopes-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAepD,qBAAa,yBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEnF,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CAyBrD"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TwgPreviewScopesValidator = void 0;
4
+ const text_1 = require("../text");
5
+ const utils_1 = require("../utils");
6
+ const scopes_1 = require("../utils/scopes");
7
+ const TWG_PREVIEW_SCOPES = ['read:graph:jira', 'read:graph:confluence'];
8
+ class TwgPreviewScopesValidator {
9
+ async validate(manifest) {
10
+ if (!manifest?.typedContent?.permissions?.scopes) {
11
+ return { success: true, manifestObject: manifest };
12
+ }
13
+ const manifestScopes = (0, scopes_1.getAllScopeKeys)(manifest.typedContent.permissions.scopes);
14
+ const foundTwgScopes = manifestScopes.filter((scope) => TWG_PREVIEW_SCOPES.includes(scope));
15
+ if (foundTwgScopes.length > 0) {
16
+ return {
17
+ success: true,
18
+ manifestObject: manifest,
19
+ errors: [
20
+ {
21
+ message: text_1.errors.twgPreviewScopes(foundTwgScopes),
22
+ reference: text_1.References.Deprecated,
23
+ level: 'warning',
24
+ ...(0, utils_1.findPosition)('scopes', manifest?.yamlContentByLine)
25
+ }
26
+ ]
27
+ };
28
+ }
29
+ return { success: true, manifestObject: manifest };
30
+ }
31
+ }
32
+ exports.TwgPreviewScopesValidator = TwgPreviewScopesValidator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/manifest",
3
- "version": "12.0.0",
3
+ "version": "12.1.0-experimental-8b78d46",
4
4
  "description": "Definitions and validations of the Forge manifest",
5
5
  "main": "out/index.js",
6
6
  "scripts": {