@forge/lint 3.4.1-next.5 → 3.5.0-next.7
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 +13 -0
- package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.d.ts +0 -1
- package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.d.ts.map +1 -1
- package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.js +2 -10
- package/out/lint/linters/permission-linter/api-call-interface.d.ts +7 -2
- package/out/lint/linters/permission-linter/api-call-interface.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/api-call-interface.js +1 -0
- package/out/lint/linters/permission-linter/permission-linter.d.ts +2 -1
- package/out/lint/linters/permission-linter/permission-linter.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/permission-linter.js +6 -0
- package/out/lint/linters/permission-linter/verifiers/external-fetch-verifier.d.ts +0 -1
- package/out/lint/linters/permission-linter/verifiers/external-fetch-verifier.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/verifiers/external-fetch-verifier.js +2 -10
- package/out/lint/linters/permission-linter/verifiers/image-url-verifier.d.ts +11 -0
- package/out/lint/linters/permission-linter/verifiers/image-url-verifier.d.ts.map +1 -0
- package/out/lint/linters/permission-linter/verifiers/image-url-verifier.js +35 -0
- package/out/lint/linters/permission-linter/verifiers/index.d.ts +1 -0
- package/out/lint/linters/permission-linter/verifiers/index.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/verifiers/index.js +1 -0
- package/out/lint/linters/permission-linter/visitors/image-url-visitor.d.ts +11 -0
- package/out/lint/linters/permission-linter/visitors/image-url-visitor.d.ts.map +1 -0
- package/out/lint/linters/permission-linter/visitors/image-url-visitor.js +57 -0
- package/out/lint/linters/permission-linter/visitors/index.d.ts +1 -0
- package/out/lint/linters/permission-linter/visitors/index.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/visitors/index.js +1 -0
- package/out/lint/linters/utils.d.ts +4 -0
- package/out/lint/linters/utils.d.ts.map +1 -0
- package/out/lint/linters/utils.js +12 -0
- package/out/lint/text/messages.d.ts +4 -0
- package/out/lint/text/messages.d.ts.map +1 -1
- package/out/lint/text/messages.js +4 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @forge/lint
|
|
2
2
|
|
|
3
|
+
## 3.5.0-next.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [d94f614e]
|
|
8
|
+
- @forge/cli-shared@3.12.0-next.6
|
|
9
|
+
|
|
10
|
+
## 3.5.0-next.6
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- cf0ab7be: Add egress permissions check for Image component URLs
|
|
15
|
+
|
|
3
16
|
## 3.4.1-next.5
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export declare class DynamicPropertiesIconVerifier extends AbstractDynamicProper
|
|
|
7
7
|
private egressFilteringService;
|
|
8
8
|
constructor(environment: string, manifest: Manifest);
|
|
9
9
|
protected getLintClass(): LintClass;
|
|
10
|
-
private extractDomain;
|
|
11
10
|
process(iconUrls: DynamicPropertiesIconUrl[]): Promise<LintResultRule[]>;
|
|
12
11
|
}
|
|
13
12
|
//# sourceMappingURL=dynamic-properties-icon-verifier.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-properties-icon-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/dynamic-properties-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,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAE3F,qBAAa,6BACX,SAAQ,iCACR,YAAW,iBAAiB,CAAC,wBAAwB,EAAE,CAAC;IACxD,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IASnD,SAAS,CAAC,YAAY,IAAI,SAAS;
|
|
1
|
+
{"version":3,"file":"dynamic-properties-icon-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/dynamic-properties-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,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAE3F,qBAAa,6BACX,SAAQ,iCACR,YAAW,iBAAiB,CAAC,wBAAwB,EAAE,CAAC;IACxD,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IASnD,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,QAAQ,EAAE,wBAAwB,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAmBtF"}
|
package/out/lint/linters/dynamic-properties-linter/verifiers/dynamic-properties-icon-verifier.js
CHANGED
|
@@ -3,21 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DynamicPropertiesIconVerifier = void 0;
|
|
4
4
|
const egress_1 = require("@forge/egress");
|
|
5
5
|
const linter_interface_1 = require("../../../linter-interface");
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
6
7
|
const text_1 = require("../../../text");
|
|
7
|
-
const url_1 = require("url");
|
|
8
8
|
const abstract_dynamic_properties_verifier_1 = require("./abstract-dynamic-properties-verifier");
|
|
9
9
|
class DynamicPropertiesIconVerifier extends abstract_dynamic_properties_verifier_1.AbstractDynamicPropertiesVerifier {
|
|
10
10
|
constructor(environment, manifest) {
|
|
11
11
|
var _a, _b, _c, _d;
|
|
12
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
13
|
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 : [];
|
|
22
14
|
const collectedUrls = allowList.filter((item) => typeof item === 'string');
|
|
23
15
|
this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls);
|
|
@@ -39,7 +31,7 @@ class DynamicPropertiesIconVerifier extends abstract_dynamic_properties_verifier
|
|
|
39
31
|
column: iconUrl.column,
|
|
40
32
|
line: iconUrl.line,
|
|
41
33
|
metadata: {
|
|
42
|
-
missingExternalImagesPermission:
|
|
34
|
+
missingExternalImagesPermission: (0, utils_1.extractDomain)(iconUrl)
|
|
43
35
|
}
|
|
44
36
|
}))
|
|
45
37
|
];
|
|
@@ -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
|
+
'IMAGE' = 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 ImageUrl extends LintCriteriaMatch {
|
|
29
|
+
type: ApiCallTypes.IMAGE;
|
|
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 | ImageUrl | ContentPropertyApiCall;
|
|
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;
|
|
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,OAAO,IAAA;CACR;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,QAAS,SAAQ,iBAAiB;IACjD,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC;IACzB,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,QAAQ,GACR,sBAAsB,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["IMAGE"] = 5] = "IMAGE";
|
|
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, ExternalApiCall, ImageUrl, ProductApiCall, StorageApiCall, UIHookApiCall } from './api-call-interface';
|
|
5
5
|
import { PathMethods } from './verifiers';
|
|
6
6
|
interface SwaggerFormat {
|
|
7
7
|
paths: {
|
|
@@ -18,6 +18,7 @@ interface PermissionLintCriteriaMatches {
|
|
|
18
18
|
storage: StorageApiCall[];
|
|
19
19
|
uiHook: UIHookApiCall[];
|
|
20
20
|
external: ExternalApiCall[];
|
|
21
|
+
image: ImageUrl[];
|
|
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,
|
|
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,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAOL,WAAW,EAGZ,MAAM,aAAa,CAAC;AAWrB,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,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;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"}
|
|
@@ -109,6 +109,7 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
109
109
|
new visitors_1.UIHookNodeVisitor(),
|
|
110
110
|
new visitors_1.StorageAPINodeVisitor(),
|
|
111
111
|
new visitors_1.ExternalApiCallVisitor(),
|
|
112
|
+
new visitors_1.ImageUrlVisitor(),
|
|
112
113
|
new visitors_1.ContentPropertyVisitor()
|
|
113
114
|
];
|
|
114
115
|
const humanReadableEnvironment = (0, cli_shared_1.environmentToOption)(this.environment);
|
|
@@ -118,6 +119,7 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
118
119
|
storage: new verifiers_1.StorageAPIVerifier(humanReadableEnvironment, this.manifest),
|
|
119
120
|
uiHook: new verifiers_1.UIHookVerifier(humanReadableEnvironment, this.manifest),
|
|
120
121
|
external: new verifiers_1.ExternalFetchVerifier(humanReadableEnvironment, this.manifest),
|
|
122
|
+
image: new verifiers_1.ImageUrlVerifier(humanReadableEnvironment, this.manifest),
|
|
121
123
|
contentProperty: new verifiers_1.ContentPropertyVerifier(humanReadableEnvironment, this.manifest)
|
|
122
124
|
};
|
|
123
125
|
}
|
|
@@ -130,6 +132,7 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
130
132
|
uiHook: [],
|
|
131
133
|
storage: [],
|
|
132
134
|
external: [],
|
|
135
|
+
image: [],
|
|
133
136
|
contentProperty: []
|
|
134
137
|
});
|
|
135
138
|
}
|
|
@@ -151,6 +154,9 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
151
154
|
case api_call_interface_1.ApiCallTypes.EXTERNAL:
|
|
152
155
|
criteriaMatches.external.push(apiCall);
|
|
153
156
|
break;
|
|
157
|
+
case api_call_interface_1.ApiCallTypes.IMAGE:
|
|
158
|
+
criteriaMatches.image.push(apiCall);
|
|
159
|
+
break;
|
|
154
160
|
case api_call_interface_1.ApiCallTypes.CONTENT_PROPERTY:
|
|
155
161
|
criteriaMatches.contentProperty.push(apiCall);
|
|
156
162
|
break;
|
|
@@ -6,7 +6,6 @@ export declare class ExternalFetchVerifier extends BaseLintIssueVerifier impleme
|
|
|
6
6
|
private egressFilteringService;
|
|
7
7
|
constructor(environment: string, manifest: Manifest);
|
|
8
8
|
protected getLintClass(): LintClass;
|
|
9
|
-
private extractDomain;
|
|
10
9
|
process(fetchCalls: ExternalApiCall[]): Promise<LintResultRule[]>;
|
|
11
10
|
}
|
|
12
11
|
//# sourceMappingURL=external-fetch-verifier.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-fetch-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/external-fetch-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,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,qBAAa,qBAAsB,SAAQ,qBAAsB,YAAW,iBAAiB,CAAC,eAAe,EAAE,CAAC;IAC9G,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAenD,SAAS,CAAC,YAAY,IAAI,SAAS;
|
|
1
|
+
{"version":3,"file":"external-fetch-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/external-fetch-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,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,qBAAa,qBAAsB,SAAQ,qBAAsB,YAAW,iBAAiB,CAAC,eAAe,EAAE,CAAC;IAC9G,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAenD,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAc/E"}
|
|
@@ -5,19 +5,11 @@ const egress_1 = require("@forge/egress");
|
|
|
5
5
|
const linter_interface_1 = require("../../../linter-interface");
|
|
6
6
|
const verifier_interface_1 = require("../../verifier-interface");
|
|
7
7
|
const text_1 = require("../../../text");
|
|
8
|
-
const
|
|
8
|
+
const utils_1 = require("../../utils");
|
|
9
9
|
class ExternalFetchVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
10
10
|
constructor(environment, manifest) {
|
|
11
11
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
12
12
|
super(environment, manifest);
|
|
13
|
-
this.extractDomain = (fetchCall) => {
|
|
14
|
-
try {
|
|
15
|
-
return new url_1.URL(fetchCall.url).hostname;
|
|
16
|
-
}
|
|
17
|
-
catch (e) {
|
|
18
|
-
return fetchCall.url;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
13
|
const allowList = (_e = (_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.fetch) === null || _d === void 0 ? void 0 : _d.backend) !== null && _e !== void 0 ? _e : [];
|
|
22
14
|
const remoteList = (_g = (_f = this.manifest) === null || _f === void 0 ? void 0 : _f.remotes) !== null && _g !== void 0 ? _g : [];
|
|
23
15
|
const collectedUrls = allowList.filter((item) => typeof item === 'string');
|
|
@@ -39,7 +31,7 @@ class ExternalFetchVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
|
39
31
|
column: fetchCall.column,
|
|
40
32
|
line: fetchCall.line,
|
|
41
33
|
metadata: {
|
|
42
|
-
missingExternalFetchPermission:
|
|
34
|
+
missingExternalFetchPermission: (0, utils_1.extractDomain)(fetchCall)
|
|
43
35
|
}
|
|
44
36
|
}));
|
|
45
37
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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 { ImageUrl } from '../api-call-interface';
|
|
5
|
+
export declare class ImageUrlVerifier extends BaseLintIssueVerifier implements LintIssueVerifier<ImageUrl[]> {
|
|
6
|
+
private egressFilteringService;
|
|
7
|
+
constructor(environment: string, manifest: Manifest);
|
|
8
|
+
protected getLintClass(): LintClass;
|
|
9
|
+
process(imageUrls: ImageUrl[]): Promise<LintResultRule[]>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=image-url-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-url-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/image-url-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,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjD,qBAAa,gBAAiB,SAAQ,qBAAsB,YAAW,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IAClG,OAAO,CAAC,sBAAsB,CAAyB;gBAE3C,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;IAUnD,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAcvE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImageUrlVerifier = 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 utils_1 = require("../../utils");
|
|
9
|
+
class ImageUrlVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
10
|
+
constructor(environment, manifest) {
|
|
11
|
+
var _a, _b, _c, _d;
|
|
12
|
+
super(environment, manifest);
|
|
13
|
+
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 : [];
|
|
14
|
+
const collectedUrls = allowList.filter((item) => typeof item === 'string');
|
|
15
|
+
this.egressFilteringService = new egress_1.EgressFilteringService(collectedUrls);
|
|
16
|
+
}
|
|
17
|
+
getLintClass() {
|
|
18
|
+
return linter_interface_1.LintClass.Error;
|
|
19
|
+
}
|
|
20
|
+
async process(imageUrls) {
|
|
21
|
+
return imageUrls
|
|
22
|
+
.filter(({ url }) => !this.egressFilteringService.isValidUrl(url))
|
|
23
|
+
.map((imageUrl) => ({
|
|
24
|
+
class: this.getLintClass(),
|
|
25
|
+
message: text_1.messages.verifiers.imageUrl.message(imageUrl.url),
|
|
26
|
+
reference: text_1.messages.verifiers.imageUrl.reference,
|
|
27
|
+
column: imageUrl.column,
|
|
28
|
+
line: imageUrl.line,
|
|
29
|
+
metadata: {
|
|
30
|
+
missingExternalImagesPermission: (0, utils_1.extractDomain)(imageUrl)
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.ImageUrlVerifier = ImageUrlVerifier;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC"}
|
|
@@ -6,3 +6,4 @@ tslib_1.__exportStar(require("./storage-api-verifier"), exports);
|
|
|
6
6
|
tslib_1.__exportStar(require("./ui-hook-verifier"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./external-fetch-verifier"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./content-property-verifier"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./image-url-verifier"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
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 ImageUrlVisitor implements NodeVisitor<ApiCall> {
|
|
5
|
+
static ABSOLUTE_URL_REGEX: RegExp;
|
|
6
|
+
visit(node: TSESTree.Node, _parent: TSESTree.Node | undefined, callback: (apiCall: ApiCall) => void): void;
|
|
7
|
+
private getImageUrlNode;
|
|
8
|
+
private isBundledUri;
|
|
9
|
+
private isAbsoluteUrl;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=image-url-visitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-url-visitor.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/image-url-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAA0B,MAAM,uBAAuB,CAAC;AAExE,qBAAa,eAAgB,YAAW,WAAW,CAAC,OAAO,CAAC;IAC1D,MAAM,CAAC,kBAAkB,SAAyB;IAE3C,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAgCjH,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;CAGtB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImageUrlVisitor = void 0;
|
|
4
|
+
const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
|
|
5
|
+
const api_call_interface_1 = require("../api-call-interface");
|
|
6
|
+
class ImageUrlVisitor {
|
|
7
|
+
visit(node, _parent, callback) {
|
|
8
|
+
const imageUrlNode = this.getImageUrlNode(node);
|
|
9
|
+
if (!imageUrlNode) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
if ((imageUrlNode === null || imageUrlNode === void 0 ? void 0 : imageUrlNode.type) === typescript_estree_1.AST_NODE_TYPES.JSXAttribute) {
|
|
13
|
+
const imageUrlAttribute = imageUrlNode.value;
|
|
14
|
+
if (imageUrlAttribute &&
|
|
15
|
+
imageUrlAttribute.type === typescript_estree_1.AST_NODE_TYPES.Literal &&
|
|
16
|
+
typeof imageUrlAttribute.value === 'string') {
|
|
17
|
+
if (imageUrlAttribute.value.trim() !== '' &&
|
|
18
|
+
!this.isBundledUri(imageUrlAttribute.value) &&
|
|
19
|
+
this.isAbsoluteUrl(imageUrlAttribute.value)) {
|
|
20
|
+
const imageUrl = {
|
|
21
|
+
type: api_call_interface_1.ApiCallTypes.IMAGE,
|
|
22
|
+
url: imageUrlAttribute.value,
|
|
23
|
+
line: imageUrlAttribute.loc.start.line,
|
|
24
|
+
column: imageUrlAttribute.loc.start.column
|
|
25
|
+
};
|
|
26
|
+
callback(imageUrl);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
getImageUrlNode(node) {
|
|
32
|
+
if (node.type !== typescript_estree_1.AST_NODE_TYPES.JSXOpeningElement) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const { name, attributes } = node;
|
|
36
|
+
if (name.type === typescript_estree_1.AST_NODE_TYPES.JSXIdentifier && name.name === 'Image') {
|
|
37
|
+
return attributes.find((attribute) => {
|
|
38
|
+
if (attribute.type !== typescript_estree_1.AST_NODE_TYPES.JSXAttribute) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (attribute.name.type === typescript_estree_1.AST_NODE_TYPES.JSXIdentifier && attribute.name.name === 'src') {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
isBundledUri(imageUri) {
|
|
50
|
+
return imageUri.startsWith('resource:') || imageUri.startsWith('data:image');
|
|
51
|
+
}
|
|
52
|
+
isAbsoluteUrl(url) {
|
|
53
|
+
return ImageUrlVisitor.ABSOLUTE_URL_REGEX.test(url);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.ImageUrlVisitor = ImageUrlVisitor;
|
|
57
|
+
ImageUrlVisitor.ABSOLUTE_URL_REGEX = /^(?:[a-z+]+:)?\/\//i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC"}
|
|
@@ -6,3 +6,4 @@ tslib_1.__exportStar(require("./storage-api-node-visitor"), exports);
|
|
|
6
6
|
tslib_1.__exportStar(require("./ui-hook-node-visitor"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./external-fetch-call-visitor"), exports);
|
|
8
8
|
tslib_1.__exportStar(require("./content-property-visitor"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./image-url-visitor"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lint/linters/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,eAAgB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,WAMxD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractDomain = void 0;
|
|
4
|
+
const extractDomain = (urlAstNode) => {
|
|
5
|
+
try {
|
|
6
|
+
return new URL(urlAstNode.url).hostname;
|
|
7
|
+
}
|
|
8
|
+
catch (e) {
|
|
9
|
+
return urlAstNode.url;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
exports.extractDomain = extractDomain;
|
|
@@ -13,6 +13,10 @@ export declare const messages: {
|
|
|
13
13
|
warning: () => string;
|
|
14
14
|
reference: string;
|
|
15
15
|
};
|
|
16
|
+
imageUrl: {
|
|
17
|
+
message: (url: string) => string;
|
|
18
|
+
reference: string;
|
|
19
|
+
};
|
|
16
20
|
handler: {
|
|
17
21
|
message: (method: string, key: string) => string;
|
|
18
22
|
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;;;;2BAIN,MAAM;2BAER,MAAM;;;;
|
|
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;2BAER,MAAM;;;;2BAKJ,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"}
|
|
@@ -16,6 +16,10 @@ exports.messages = {
|
|
|
16
16
|
warning: () => `When using dynamic content properties along with icons, make sure to add the icon URL into the external images permissions of your app manifest. Otherwise, the icon will not be rendered.`,
|
|
17
17
|
reference: 'egress-permission-required'
|
|
18
18
|
},
|
|
19
|
+
imageUrl: {
|
|
20
|
+
message: (url) => `The domain ${url} is not included in the external images permissions of your app manifest`,
|
|
21
|
+
reference: 'egress-permission-required'
|
|
22
|
+
},
|
|
19
23
|
handler: {
|
|
20
24
|
message: (method, key) => `Cannot find exported function '${method}', which is required by module '${key}' handler defined in the manifest`,
|
|
21
25
|
reference: 'valid-module-required'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/lint",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0-next.7",
|
|
4
4
|
"description": "Linting for forge apps",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@types/node-fetch": "^2.5.7"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@forge/cli-shared": "3.12.0-next.
|
|
20
|
+
"@forge/cli-shared": "3.12.0-next.6",
|
|
21
21
|
"@forge/egress": "1.2.1",
|
|
22
22
|
"@forge/manifest": "4.13.0-next.3",
|
|
23
23
|
"@typescript-eslint/typescript-estree": "^5.40.0",
|