@forge/lint 3.2.22-next.4 → 3.3.0-next.5

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.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,22 @@
1
1
  # @forge/lint
2
2
 
3
- ## 3.2.22-next.4
3
+ ## 3.3.0-next.5
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - Updated dependencies [9c3f9e4]
7
+ - 2da63a57: Bumping dependencies via Renovate:
8
+
9
+ - atlassian-openapi
10
+
11
+ ## 3.3.0-next.4
12
+
13
+ ### Minor Changes
14
+
15
+ - d50d90b8: Add ability to detect missing image permissions when using Confluence contentByLineItem modules with dynamic properties
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [9c3f9e47]
8
20
  - @forge/manifest@4.10.0-next.2
9
21
  - @forge/cli-shared@3.11.0-next.4
10
22
 
@@ -4,7 +4,8 @@ export declare enum ApiCallTypes {
4
4
  'HOOK' = 1,
5
5
  'STORAGE' = 2,
6
6
  'EXTERNAL' = 3,
7
- 'CONTENT_PROPERTY' = 4
7
+ 'CONTENT_PROPERTY' = 4,
8
+ 'DYNAMIC_PROPERTIES_ICON' = 5
8
9
  }
9
10
  export interface ProductApiCall extends LintCriteriaMatch {
10
11
  type: ApiCallTypes.PRODUCT;
@@ -24,10 +25,14 @@ export interface ExternalApiCall extends LintCriteriaMatch {
24
25
  type: ApiCallTypes.EXTERNAL;
25
26
  url: string;
26
27
  }
28
+ export interface DynamicPropertiesIconUrl extends LintCriteriaMatch {
29
+ type: ApiCallTypes.DYNAMIC_PROPERTIES_ICON;
30
+ url: string;
31
+ }
27
32
  export interface ContentPropertyApiCall extends LintCriteriaMatch {
28
33
  type: ApiCallTypes.CONTENT_PROPERTY;
29
34
  context: string;
30
35
  method: string;
31
36
  }
32
- export declare type ApiCall = ProductApiCall | UIHookApiCall | StorageApiCall | ExternalApiCall | ContentPropertyApiCall;
37
+ export declare type ApiCall = ProductApiCall | UIHookApiCall | StorageApiCall | ExternalApiCall | ContentPropertyApiCall | DynamicPropertiesIconUrl;
33
38
  //# sourceMappingURL=api-call-interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-call-interface.d.ts","sourceRoot":"","sources":["../../../../src/lint/linters/permission-linter/api-call-interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,oBAAY,YAAY;IACtB,SAAS,IAAA;IACT,MAAM,IAAA;IACN,SAAS,IAAA;IACT,UAAU,IAAA;IACV,kBAAkB,IAAA;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,IAAI,EAAE,YAAY,CAAC,gBAAgB,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,OAAO,GAAG,cAAc,GAAG,aAAa,GAAG,cAAc,GAAG,eAAe,GAAG,sBAAsB,CAAC"}
1
+ {"version":3,"file":"api-call-interface.d.ts","sourceRoot":"","sources":["../../../../src/lint/linters/permission-linter/api-call-interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,oBAAY,YAAY;IACtB,SAAS,IAAA;IACT,MAAM,IAAA;IACN,SAAS,IAAA;IACT,UAAU,IAAA;IACV,kBAAkB,IAAA;IAClB,yBAAyB,IAAA;CAC1B;AAED,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,eAAgB,SAAQ,iBAAiB;IACxD,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE,IAAI,EAAE,YAAY,CAAC,uBAAuB,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,IAAI,EAAE,YAAY,CAAC,gBAAgB,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oBAAY,OAAO,GACf,cAAc,GACd,aAAa,GACb,cAAc,GACd,eAAe,GACf,sBAAsB,GACtB,wBAAwB,CAAC"}
@@ -8,4 +8,5 @@ var ApiCallTypes;
8
8
  ApiCallTypes[ApiCallTypes["STORAGE"] = 2] = "STORAGE";
9
9
  ApiCallTypes[ApiCallTypes["EXTERNAL"] = 3] = "EXTERNAL";
10
10
  ApiCallTypes[ApiCallTypes["CONTENT_PROPERTY"] = 4] = "CONTENT_PROPERTY";
11
+ ApiCallTypes[ApiCallTypes["DYNAMIC_PROPERTIES_ICON"] = 5] = "DYNAMIC_PROPERTIES_ICON";
11
12
  })(ApiCallTypes = exports.ApiCallTypes || (exports.ApiCallTypes = {}));
@@ -1,7 +1,7 @@
1
1
  import type { ManifestSchema as Manifest } from '@forge/manifest';
2
2
  import BaseLinter from '../../base-linter';
3
3
  import { LintFixState, LintLogger, LintResultRule } from '../../linter-interface';
4
- import { ApiCall, ExternalApiCall, ProductApiCall, StorageApiCall, UIHookApiCall } from './api-call-interface';
4
+ import { ApiCall, DynamicPropertiesIconUrl, ExternalApiCall, ProductApiCall, StorageApiCall, UIHookApiCall } from './api-call-interface';
5
5
  import { PathMethods } from './verifiers';
6
6
  interface SwaggerFormat {
7
7
  paths: {
@@ -9,7 +9,7 @@ interface SwaggerFormat {
9
9
  };
10
10
  }
11
11
  export declare const NON_FWD_SLASH_REGEX = "[^\\/\\s]*";
12
- export declare const findMissingPermissions: (errors: LintResultRule[], warnings: LintResultRule[], permissionsType: 'missingPermission' | 'missingExternalFetchPermission' | 'missingContentStylePermission', state?: LintFixState) => Set<string>;
12
+ export declare const findMissingPermissions: (errors: LintResultRule[], warnings: LintResultRule[], permissionsType: 'missingPermission' | 'missingExternalFetchPermission' | 'missingContentStylePermission' | 'missingExternalImagesPermission', state?: LintFixState) => Set<string>;
13
13
  export declare const fixMissingPermissions: (errors: LintResultRule[], warnings: LintResultRule[], state: LintFixState) => Promise<LintFixState>;
14
14
  interface PermissionLintCriteriaMatches {
15
15
  [key: string]: ApiCall[];
@@ -18,6 +18,7 @@ interface PermissionLintCriteriaMatches {
18
18
  storage: StorageApiCall[];
19
19
  uiHook: UIHookApiCall[];
20
20
  external: ExternalApiCall[];
21
+ dynamicPropertiesIcon: DynamicPropertiesIconUrl[];
21
22
  }
22
23
  export declare class PermissionLinter extends BaseLinter<ApiCall, PermissionLintCriteriaMatches, ApiCall[]> {
23
24
  private manifest;
@@ -1 +1 @@
1
- {"version":3,"file":"permission-linter.d.ts","sourceRoot":"","sources":["../../../../src/lint/linters/permission-linter/permission-linter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,IAAI,QAAQ,EAAe,MAAM,iBAAiB,CAAC;AAE/E,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EACL,OAAO,EAEP,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAML,WAAW,EAGZ,MAAM,aAAa,CAAC;AAUrB,UAAU,aAAa;IACrB,KAAK,EAAE;QACL,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;KAC7B,CAAC;CACH;AAED,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAKhD,eAAO,MAAM,sBAAsB,WACzB,cAAc,EAAE,YACd,cAAc,EAAE,mBACT,mBAAmB,GAAG,gCAAgC,GAAG,+BAA+B,UACjG,YAAY,KACnB,IAAI,MAAM,CAkBZ,CAAC;AAEF,eAAO,MAAM,qBAAqB,WACxB,cAAc,EAAE,YACd,cAAc,EAAE,SACnB,YAAY,KAClB,QAAQ,YAAY,CAsEtB,CAAC;AAEF,UAAU,6BAA6B;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,qBAAa,gBAAiB,SAAQ,UAAU,CAAC,OAAO,EAAE,6BAA6B,EAAE,OAAO,EAAE,CAAC;IAUhE,OAAO,CAAC,QAAQ;IATjD,MAAM,CAAC,cAAc,SAAgC;IACrD,MAAM,CAAC,aAAa,SAA+B;IACnD,MAAM,CAAC,aAAa,SAA+B;IACnD,MAAM,CAAC,oBAAoB,SAAsC;IAEjE,OAAO,CAAC,IAAI,CAAC,CAA0B;IACvC,OAAO,CAAC,UAAU,CAAC,CAA0B;IAC7C,OAAO,CAAC,KAAK,CAAC,CAAa;gBAEf,WAAW,EAAE,MAAM,EAAU,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU;IAIlE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAgEvC,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAajD,SAAS,CAAC,QAAQ,IACd,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC,GACtG,SAAS;IAIb,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAsB3D,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAWtE,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAKrE,OAAO,CAAC,YAAY;CAarB"}
1
+ {"version":3,"file":"permission-linter.d.ts","sourceRoot":"","sources":["../../../../src/lint/linters/permission-linter/permission-linter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,IAAI,QAAQ,EAAe,MAAM,iBAAiB,CAAC;AAE/E,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EACL,OAAO,EAEP,wBAAwB,EACxB,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAML,WAAW,EAGZ,MAAM,aAAa,CAAC;AAYrB,UAAU,aAAa;IACrB,KAAK,EAAE;QACL,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;KAC7B,CAAC;CACH;AAED,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAKhD,eAAO,MAAM,sBAAsB,WACzB,cAAc,EAAE,YACd,cAAc,EAAE,mBAEtB,mBAAmB,GACnB,gCAAgC,GAChC,+BAA+B,GAC/B,iCAAiC,UAC7B,YAAY,KACnB,IAAI,MAAM,CAkBZ,CAAC;AAEF,eAAO,MAAM,qBAAqB,WACxB,cAAc,EAAE,YACd,cAAc,EAAE,SACnB,YAAY,KAClB,QAAQ,YAAY,CAgEtB,CAAC;AAEF,UAAU,6BAA6B;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAAC;IACzB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,qBAAqB,EAAE,wBAAwB,EAAE,CAAC;CACnD;AAED,qBAAa,gBAAiB,SAAQ,UAAU,CAAC,OAAO,EAAE,6BAA6B,EAAE,OAAO,EAAE,CAAC;IAUhE,OAAO,CAAC,QAAQ;IATjD,MAAM,CAAC,cAAc,SAAgC;IACrD,MAAM,CAAC,aAAa,SAA+B;IACnD,MAAM,CAAC,aAAa,SAA+B;IACnD,MAAM,CAAC,oBAAoB,SAAsC;IAEjE,OAAO,CAAC,IAAI,CAAC,CAA0B;IACvC,OAAO,CAAC,UAAU,CAAC,CAA0B;IAC7C,OAAO,CAAC,KAAK,CAAC,CAAa;gBAEf,WAAW,EAAE,MAAM,EAAU,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU;IAIlE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAkEvC,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAcjD,SAAS,CAAC,QAAQ,IACd,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC,GACtG,SAAS;IAIb,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAyB3D,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAWtE,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAKrE,OAAO,CAAC,YAAY;CAarB"}
@@ -9,6 +9,8 @@ const api_call_interface_1 = require("./api-call-interface");
9
9
  const verifiers_1 = require("./verifiers");
10
10
  const visitors_1 = require("./visitors");
11
11
  const fs_1 = tslib_1.__importDefault(require("fs"));
12
+ const dynamic_properties_icon_verifier_1 = require("./verifiers/dynamic-properties-icon-verifier");
13
+ const dynamic_properties_icon_visitor_1 = require("./visitors/dynamic-properties-icon-visitor");
12
14
  exports.NON_FWD_SLASH_REGEX = '[^\\/\\s]*';
13
15
  const CACHE_KEY = 'PERMISSIONS_LINTER';
14
16
  const ONE_HOUR_MS = 1000 * 60 * 60;
@@ -32,10 +34,11 @@ const findMissingPermissions = (errors, warnings, permissionsType, state) => {
32
34
  };
33
35
  exports.findMissingPermissions = findMissingPermissions;
34
36
  const fixMissingPermissions = async (errors, warnings, state) => {
35
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
37
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
36
38
  const missingScopes = (0, exports.findMissingPermissions)(errors, warnings, 'missingPermission', state);
37
39
  const missingExternalFetchBackend = (0, exports.findMissingPermissions)(errors, warnings, 'missingExternalFetchPermission', state);
38
40
  const missingContentStyle = (0, exports.findMissingPermissions)(errors, warnings, 'missingContentStylePermission', state);
41
+ const missingExternalImage = (0, exports.findMissingPermissions)(errors, warnings, 'missingExternalImagesPermission', state);
39
42
  const currentPermissions = (_b = (_a = (await state.configFile.readConfig())) === null || _a === void 0 ? void 0 : _a.permissions) !== null && _b !== void 0 ? _b : {};
40
43
  const currentRemotes = (_d = (_c = (await state.configFile.readConfig())) === null || _c === void 0 ? void 0 : _c.remotes) !== null && _d !== void 0 ? _d : [];
41
44
  const currentScopes = (_e = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.scopes) !== null && _e !== void 0 ? _e : [];
@@ -54,26 +57,20 @@ const fixMissingPermissions = async (errors, warnings, state) => {
54
57
  const currentContentStyles = (_k = (_j = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.content) === null || _j === void 0 ? void 0 : _j.styles) !== null && _k !== void 0 ? _k : [];
55
58
  currentContentStyles.forEach((e) => missingContentStyle.add(e));
56
59
  const arrayMissingContentStyles = [...missingContentStyle];
57
- await state.configFile.writeToConfigFile('permissions', Object.assign(Object.assign(Object.assign(Object.assign({}, currentPermissions), { scopes: [...missingScopes] }), (arrayMissingExternalFetchBackend.length > 0
58
- ? {
59
- external: currentPermissions.external
60
- ? Object.assign(Object.assign({}, currentPermissions.external), { fetch: currentPermissions.external.fetch
61
- ? Object.assign(Object.assign({}, currentPermissions.external.fetch), { backend: arrayMissingExternalFetchBackend }) : {
62
- backend: arrayMissingExternalFetchBackend
63
- } }) : {
64
- fetch: {
65
- backend: arrayMissingExternalFetchBackend
66
- }
67
- }
68
- }
69
- : {})), (arrayMissingContentStyles.length > 0
70
- ? {
71
- content: currentPermissions.content
72
- ? Object.assign(Object.assign({}, currentPermissions.content), { styles: arrayMissingContentStyles }) : {
73
- styles: arrayMissingContentStyles
74
- }
75
- }
76
- : {})));
60
+ const currentExternalImages = (_m = (_l = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.external) === null || _l === void 0 ? void 0 : _l.images) !== null && _m !== void 0 ? _m : [];
61
+ currentExternalImages.forEach((e) => missingExternalImage.add(e));
62
+ const arrayMissingExternalImages = [...missingExternalImage];
63
+ const config = Object.assign(Object.assign({}, currentPermissions), { scopes: [...missingScopes] });
64
+ if (arrayMissingExternalFetchBackend.length > 0) {
65
+ config.external = Object.assign(Object.assign({}, config.external), { fetch: Object.assign(Object.assign({}, (_o = config.external) === null || _o === void 0 ? void 0 : _o.fetch), { backend: arrayMissingExternalFetchBackend }) });
66
+ }
67
+ if (arrayMissingExternalImages.length > 0) {
68
+ config.external = Object.assign(Object.assign({}, config.external), { images: arrayMissingExternalImages });
69
+ }
70
+ if (arrayMissingContentStyles.length > 0) {
71
+ config.content = Object.assign(Object.assign({}, config.content), { styles: arrayMissingContentStyles });
72
+ }
73
+ await state.configFile.writeToConfigFile('permissions', config);
77
74
  return state;
78
75
  };
79
76
  exports.fixMissingPermissions = fixMissingPermissions;
@@ -114,7 +111,8 @@ class PermissionLinter extends base_linter_1.default {
114
111
  new visitors_1.UIHookNodeVisitor(),
115
112
  new visitors_1.StorageAPINodeVisitor(),
116
113
  new visitors_1.ExternalApiCallVisitor(),
117
- new visitors_1.ContentPropertyVisitor()
114
+ new visitors_1.ContentPropertyVisitor(),
115
+ new dynamic_properties_icon_visitor_1.DynamicPropertiesIconVisitor()
118
116
  ];
119
117
  const humanReadableEnvironment = (0, cli_shared_1.environmentToOption)(this.environment);
120
118
  this.verifiers = {
@@ -123,7 +121,8 @@ class PermissionLinter extends base_linter_1.default {
123
121
  storage: new verifiers_1.StorageAPIVerifier(humanReadableEnvironment, this.manifest),
124
122
  uiHook: new verifiers_1.UIHookVerifier(humanReadableEnvironment, this.manifest),
125
123
  external: new verifiers_1.ExternalFetchVerifier(humanReadableEnvironment, this.manifest),
126
- contentProperty: new verifiers_1.ContentPropertyVerifier(humanReadableEnvironment, this.manifest)
124
+ contentProperty: new verifiers_1.ContentPropertyVerifier(humanReadableEnvironment, this.manifest),
125
+ dynamicPropertiesIcon: new dynamic_properties_icon_verifier_1.DynamicPropertiesIconVerifier(humanReadableEnvironment, this.manifest)
127
126
  };
128
127
  }
129
128
  setupMatchesMap(filepath) {
@@ -135,7 +134,8 @@ class PermissionLinter extends base_linter_1.default {
135
134
  uiHook: [],
136
135
  storage: [],
137
136
  external: [],
138
- contentProperty: []
137
+ contentProperty: [],
138
+ dynamicPropertiesIcon: []
139
139
  });
140
140
  }
141
141
  getFixer() {
@@ -159,6 +159,9 @@ class PermissionLinter extends base_linter_1.default {
159
159
  case api_call_interface_1.ApiCallTypes.CONTENT_PROPERTY:
160
160
  criteriaMatches.contentProperty.push(apiCall);
161
161
  break;
162
+ case api_call_interface_1.ApiCallTypes.DYNAMIC_PROPERTIES_ICON:
163
+ criteriaMatches.dynamicPropertiesIcon.push(apiCall);
164
+ break;
162
165
  }
163
166
  }
164
167
  async getProductPaths(cacheKey, url) {
@@ -0,0 +1,13 @@
1
+ import type { ManifestSchema as Manifest } from '@forge/manifest';
2
+ import { LintClass, LintResultRule } from '../../../linter-interface';
3
+ import { BaseLintIssueVerifier, LintIssueVerifier } from '../../verifier-interface';
4
+ import { DynamicPropertiesIconUrl } from '../api-call-interface';
5
+ export declare class DynamicPropertiesIconVerifier extends BaseLintIssueVerifier implements LintIssueVerifier<DynamicPropertiesIconUrl[]> {
6
+ private egressFilteringService;
7
+ private readonly shouldRunCheck;
8
+ constructor(environment: string, manifest: Manifest);
9
+ protected getLintClass(): LintClass;
10
+ private extractDomain;
11
+ process(iconUrls: DynamicPropertiesIconUrl[]): Promise<LintResultRule[]>;
12
+ }
13
+ //# sourceMappingURL=dynamic-properties-icon-verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-properties-icon-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/dynamic-properties-icon-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAGlE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAIjE,qBAAa,6BACX,SAAQ,qBACR,YAAW,iBAAiB,CAAC,wBAAwB,EAAE,CAAC;IACxD,OAAO,CAAC,sBAAsB,CAAyB;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAE7B,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAcnD,SAAS,CAAC,YAAY,IAAI,SAAS;IAInC,OAAO,CAAC,aAAa,CAMnB;IAEW,OAAO,CAAC,QAAQ,EAAE,wBAAwB,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAiBtF"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamicPropertiesIconVerifier = void 0;
4
+ const egress_1 = require("@forge/egress");
5
+ const linter_interface_1 = require("../../../linter-interface");
6
+ const verifier_interface_1 = require("../../verifier-interface");
7
+ const text_1 = require("../../../text");
8
+ const url_1 = require("url");
9
+ class DynamicPropertiesIconVerifier extends verifier_interface_1.BaseLintIssueVerifier {
10
+ constructor(environment, manifest) {
11
+ var _a, _b, _c, _d, _e, _f;
12
+ super(environment, manifest);
13
+ this.extractDomain = (iconUrl) => {
14
+ try {
15
+ return new url_1.URL(iconUrl.url).hostname;
16
+ }
17
+ catch (e) {
18
+ return iconUrl.url;
19
+ }
20
+ };
21
+ this.shouldRunCheck = false;
22
+ const allowList = (_d = (_c = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.external) === null || _c === void 0 ? void 0 : _c.images) !== null && _d !== void 0 ? _d : [];
23
+ const collectedUrls = allowList.filter((item) => typeof item === 'string');
24
+ this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls);
25
+ if ((_f = (_e = this.manifest.modules) === null || _e === void 0 ? void 0 : _e['confluence:contentBylineItem']) === null || _f === void 0 ? void 0 : _f.find((module) => { var _a; return (_a = module.dynamicProperties) === null || _a === void 0 ? void 0 : _a.function; })) {
26
+ this.shouldRunCheck = true;
27
+ }
28
+ }
29
+ getLintClass() {
30
+ return linter_interface_1.LintClass.Error;
31
+ }
32
+ async process(iconUrls) {
33
+ if (!this.shouldRunCheck) {
34
+ return [];
35
+ }
36
+ return iconUrls
37
+ .filter(({ url }) => !this.egressFilteringService.isValidUrl(url))
38
+ .map((iconUrl) => ({
39
+ class: this.getLintClass(),
40
+ message: text_1.messages.verifiers.dynamicPropertiesIcon.message(iconUrl.url),
41
+ reference: text_1.messages.verifiers.dynamicPropertiesIcon.reference,
42
+ column: iconUrl.column,
43
+ line: iconUrl.line,
44
+ metadata: {
45
+ missingExternalImagesPermission: this.extractDomain(iconUrl)
46
+ }
47
+ }));
48
+ }
49
+ }
50
+ exports.DynamicPropertiesIconVerifier = DynamicPropertiesIconVerifier;
@@ -0,0 +1,10 @@
1
+ import { TSESTree } from '@typescript-eslint/typescript-estree';
2
+ import { NodeVisitor } from '../../node-visitor-interface';
3
+ import { ApiCall } from '../api-call-interface';
4
+ export declare class DynamicPropertiesIconVisitor implements NodeVisitor<ApiCall> {
5
+ visit(node: TSESTree.Node, parent: TSESTree.Node | undefined, callback: (iconUrl: ApiCall) => void): void;
6
+ private isIconPropertyDefinition;
7
+ private handleIconNode;
8
+ private transformArgsToIconUrl;
9
+ }
10
+ //# sourceMappingURL=dynamic-properties-icon-visitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-properties-icon-visitor.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/dynamic-properties-icon-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAE9D,qBAAa,4BAA6B,YAAW,WAAW,CAAC,OAAO,CAAC;IAChE,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IA4BhH,OAAO,CAAC,wBAAwB,CAI9B;IAEF,OAAO,CAAC,cAAc,CAOpB;IAEF,OAAO,CAAC,sBAAsB,CAK3B;CACJ"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamicPropertiesIconVisitor = void 0;
4
+ const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
5
+ const api_call_interface_1 = require("../api-call-interface");
6
+ class DynamicPropertiesIconVisitor {
7
+ constructor() {
8
+ this.isIconPropertyDefinition = (node) => {
9
+ return (node.type === typescript_estree_1.AST_NODE_TYPES.Property && node.key.type === typescript_estree_1.AST_NODE_TYPES.Identifier && node.key.name === 'icon');
10
+ };
11
+ this.handleIconNode = (iconNode, callback) => {
12
+ if ((iconNode === null || iconNode === void 0 ? void 0 : iconNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal && typeof (iconNode === null || iconNode === void 0 ? void 0 : iconNode.value) === 'string') {
13
+ if (iconNode.value.trim() !== '') {
14
+ const iconUrl = this.transformArgsToIconUrl(iconNode);
15
+ callback(iconUrl);
16
+ }
17
+ }
18
+ };
19
+ this.transformArgsToIconUrl = (iconNode) => ({
20
+ type: api_call_interface_1.ApiCallTypes.DYNAMIC_PROPERTIES_ICON,
21
+ url: iconNode.value,
22
+ line: iconNode.loc.start.line,
23
+ column: iconNode.loc.start.column
24
+ });
25
+ }
26
+ visit(node, parent, callback) {
27
+ var _a, _b, _c, _d;
28
+ switch (node.type) {
29
+ case typescript_estree_1.AST_NODE_TYPES.ArrowFunctionExpression:
30
+ if (((_a = node.body) === null || _a === void 0 ? void 0 : _a.type) === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
31
+ const iconDefinitionNode = (_b = node.body) === null || _b === void 0 ? void 0 : _b.properties.find(this.isIconPropertyDefinition);
32
+ this.handleIconNode(iconDefinitionNode === null || iconDefinitionNode === void 0 ? void 0 : iconDefinitionNode.value, callback);
33
+ }
34
+ break;
35
+ case typescript_estree_1.AST_NODE_TYPES.ReturnStatement:
36
+ if (((_c = node.argument) === null || _c === void 0 ? void 0 : _c.type) === typescript_estree_1.AST_NODE_TYPES.ObjectExpression) {
37
+ const iconDefinitionNode = (_d = node.argument) === null || _d === void 0 ? void 0 : _d.properties.find(this.isIconPropertyDefinition);
38
+ this.handleIconNode(iconDefinitionNode === null || iconDefinitionNode === void 0 ? void 0 : iconDefinitionNode.value, callback);
39
+ }
40
+ break;
41
+ }
42
+ }
43
+ }
44
+ exports.DynamicPropertiesIconVisitor = DynamicPropertiesIconVisitor;
@@ -8,6 +8,10 @@ export declare const messages: {
8
8
  message: (url: string) => string;
9
9
  reference: string;
10
10
  };
11
+ dynamicPropertiesIcon: {
12
+ message: (url: string) => string;
13
+ reference: string;
14
+ };
11
15
  handler: {
12
16
  message: (method: string, key: string) => string;
13
17
  reference: string;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/lint/text/messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;+BAGI,MAAM,UAAU,MAAM,SAAS,MAAM,KAAG,MAAM;;;;2BAKlD,MAAM;;;;8BAIH,MAAM,OAAO,MAAM;;;;+BAKlB,MAAM,UAAU,MAAM,QAAQ,MAAM,GAAG,SAAS,SAAS,MAAM;;;;6BAKjE,MAAM;;;;+BAIJ,MAAM,QAAQ,MAAM,SAAS,MAAM;;;;CAK3D,CAAC"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/lint/text/messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;;+BAGI,MAAM,UAAU,MAAM,SAAS,MAAM,KAAG,MAAM;;;;2BAKlD,MAAM;;;;2BAIN,MAAM;;;;8BAKH,MAAM,OAAO,MAAM;;;;+BAKlB,MAAM,UAAU,MAAM,QAAQ,MAAM,GAAG,SAAS,SAAS,MAAM;;;;6BAKjE,MAAM;;;;+BAIJ,MAAM,QAAQ,MAAM,SAAS,MAAM;;;;CAK3D,CAAC"}
@@ -11,6 +11,10 @@ exports.messages = {
11
11
  message: (url) => `The domain ${url} is not included in the external permissions of your app manifest`,
12
12
  reference: 'egress-permission-required'
13
13
  },
14
+ dynamicPropertiesIcon: {
15
+ message: (url) => `The domain ${url} is not included in the external images permissions of your app manifest`,
16
+ reference: 'egress-permission-required'
17
+ },
14
18
  handler: {
15
19
  message: (method, key) => `Cannot find exported function '${method}', which is required by module '${key}' handler defined in the manifest`,
16
20
  reference: 'valid-module-required'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/lint",
3
- "version": "3.2.22-next.4",
3
+ "version": "3.3.0-next.5",
4
4
  "description": "Linting for forge apps",
5
5
  "main": "out/index.js",
6
6
  "license": "UNLICENSED",
@@ -22,7 +22,7 @@
22
22
  "@forge/manifest": "4.10.0-next.2",
23
23
  "@typescript-eslint/typescript-estree": "^5.40.0",
24
24
  "array.prototype.flatmap": "^1.2.3",
25
- "atlassian-openapi": "^1.0.13",
25
+ "atlassian-openapi": "^1.0.17",
26
26
  "cross-spawn": "^7.0.3",
27
27
  "node-fetch": "2.6.7"
28
28
  }