@forge/lint 0.0.0-experimental-d8cea00 → 0.0.0-experimental-c3d0263
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 +837 -4
- package/out/lint/lint.d.ts.map +1 -1
- package/out/lint/lint.js +5 -1
- package/out/lint/linters/manifest-linter/deprecated-csp-permissions-manifest-linter.d.ts +9 -0
- package/out/lint/linters/manifest-linter/deprecated-csp-permissions-manifest-linter.d.ts.map +1 -0
- package/out/lint/linters/manifest-linter/deprecated-csp-permissions-manifest-linter.js +19 -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 +34 -8
- package/out/lint/linters/permission-linter/verifiers/content-property-verifier.d.ts +6 -1
- package/out/lint/linters/permission-linter/verifiers/content-property-verifier.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/verifiers/content-property-verifier.js +66 -16
- package/out/lint/linters/permission-linter/verifiers/product-verifier.d.ts +4 -0
- package/out/lint/linters/permission-linter/verifiers/product-verifier.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/verifiers/product-verifier.js +33 -5
- package/out/lint/linters/permission-linter/verifiers/ui-hook-verifier.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/verifiers/ui-hook-verifier.js +37 -11
- package/out/lint/linters/permission-linter/visitors/external-fetch-call-visitor.d.ts +1 -0
- package/out/lint/linters/permission-linter/visitors/external-fetch-call-visitor.d.ts.map +1 -1
- package/out/lint/linters/permission-linter/visitors/external-fetch-call-visitor.js +20 -5
- package/package.json +7 -6
package/out/lint/lint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/lint/lint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/lint/lint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;AAIpB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AAQxG,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,iBAAiB,WAAY,UAAU,eAAe,UAAU,EAAE,4BAAuB,IA+CrG,CAAC;AAEF,eAAO,MAAM,YAAY,gBAAiB,UAAU,EAAE,KAAG,YAQxD,CAAC;AAEF,eAAO,MAAM,eAAe,aAChB,MAAM,UACR,OAAO,QAAQ,oBACN,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,KAChD,OAAO,CAAC,SAAS,CAOnB,CAAC;AAEF,eAAO,MAAM,IAAI,gBACF,MAAM,EAAE,YACX,QAAQ,eACL,MAAM,UACX,UAAU,6BAhBR,MAAM,UACR,OAAO,QAAQ,oBACN,OAAO,EAAE,CAAC,QAAQ,CAAC,aAAa,KAChD,OAAO,CAAC,SAAS,CAAC,YAeV,eAAe,EAAE,KAOzB,OAAO,CAAC,UAAU,EAAE,CAmCtB,CAAC;AAEF,eAAO,MAAM,QAAQ,WACX,UAAU,WACV,eAAe,KACtB,OAAO,CAAC,UAAU,EAAE,CAGtB,CAAC"}
|
package/out/lint/lint.js
CHANGED
|
@@ -12,6 +12,7 @@ const handler_linter_1 = require("./linters/handler-linter/handler-linter");
|
|
|
12
12
|
const full_manifest_linter_1 = require("./linters/manifest-linter/full-manifest-linter");
|
|
13
13
|
const permissions_manifest_linter_1 = require("./linters/manifest-linter/permissions-manifest-linter");
|
|
14
14
|
const permission_linter_1 = require("./linters/permission-linter/permission-linter");
|
|
15
|
+
const deprecated_csp_permissions_manifest_linter_1 = require("./linters/manifest-linter/deprecated-csp-permissions-manifest-linter");
|
|
15
16
|
class FailedLinterError extends Error {
|
|
16
17
|
}
|
|
17
18
|
exports.FailedLinterError = FailedLinterError;
|
|
@@ -54,7 +55,9 @@ exports.reportLintResults = (logger, lintResults, showSummary = true) => {
|
|
|
54
55
|
logger.info(cli_shared_1.Text.lint.noFixableProblems);
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
+
if (numErrors) {
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
};
|
|
60
63
|
exports.problemCount = (lintResults) => {
|
|
@@ -74,6 +77,7 @@ exports.parseSourceFile = async (filepath, parser, readFilePromise = util_1.prom
|
|
|
74
77
|
exports.lint = async (filesToLint, manifest, environment, logger, parseFunction = exports.parseSourceFile, linters = [
|
|
75
78
|
new permission_linter_1.PermissionLinter(environment, manifest, logger),
|
|
76
79
|
new permissions_manifest_linter_1.PermissionsManifestLinter(logger),
|
|
80
|
+
new deprecated_csp_permissions_manifest_linter_1.DeprecatedCspPermissionsManifestLinter(logger),
|
|
77
81
|
new full_manifest_linter_1.FullManifestLinter(logger),
|
|
78
82
|
new handler_linter_1.HandlerLinter(environment, manifest, logger)
|
|
79
83
|
]) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ManifestValidationResult, SchemaValidationError } from '@forge/manifest';
|
|
2
|
+
import { AbstractManifestLinter } from './abstract-manifest-linter';
|
|
3
|
+
import { LintResultRule, LintFixState, LintLogger } from '../../linter-interface';
|
|
4
|
+
export declare class DeprecatedCspPermissionsManifestLinter extends AbstractManifestLinter {
|
|
5
|
+
constructor(logger: LintLogger);
|
|
6
|
+
getFixer(): ((errors: LintResultRule[], warnings: LintResultRule[], state: LintFixState) => Promise<LintFixState>) | undefined;
|
|
7
|
+
getResultsForFixer(results: ManifestValidationResult<any>): SchemaValidationError[];
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=deprecated-csp-permissions-manifest-linter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deprecated-csp-permissions-manifest-linter.d.ts","sourceRoot":"","sources":["../../../../src/lint/linters/manifest-linter/deprecated-csp-permissions-manifest-linter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACnG,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGlF,qBAAa,sCAAuC,SAAQ,sBAAsB;gBACpE,MAAM,EAAE,UAAU;IAI9B,QAAQ,IACJ,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC,GACtG,SAAS;IAIb,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,CAAC,GAAG,CAAC,GAAG,qBAAqB,EAAE;CAGpF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeprecatedCspPermissionsManifestLinter = void 0;
|
|
4
|
+
const manifest_1 = require("@forge/manifest");
|
|
5
|
+
const abstract_manifest_linter_1 = require("./abstract-manifest-linter");
|
|
6
|
+
const permission_linter_1 = require("../permission-linter/permission-linter");
|
|
7
|
+
class DeprecatedCspPermissionsManifestLinter extends abstract_manifest_linter_1.AbstractManifestLinter {
|
|
8
|
+
constructor(logger) {
|
|
9
|
+
super(manifest_1.ValidationTypes.DEPRECATED_CSP_METHOD, logger);
|
|
10
|
+
}
|
|
11
|
+
getFixer() {
|
|
12
|
+
return permission_linter_1.fixMissingPermissions;
|
|
13
|
+
}
|
|
14
|
+
getResultsForFixer(results) {
|
|
15
|
+
var _a;
|
|
16
|
+
return ((_a = results.errors) === null || _a === void 0 ? void 0 : _a.filter((error) => { var _a; return (_a = error.metadata) === null || _a === void 0 ? void 0 : _a.missingContentStylePermission; })) || [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.DeprecatedCspPermissionsManifestLinter = DeprecatedCspPermissionsManifestLinter;
|
|
@@ -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', state?: LintFixState | undefined) => Set<string>;
|
|
12
|
+
export declare const findMissingPermissions: (errors: LintResultRule[], warnings: LintResultRule[], permissionsType: 'missingPermission' | 'missingExternalFetchPermission' | 'missingContentStylePermission', state?: LintFixState | undefined) => 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[];
|
|
@@ -32,6 +32,7 @@ export declare class PermissionLinter extends BaseLinter<ApiCall, PermissionLint
|
|
|
32
32
|
protected getFixer(): ((errors: LintResultRule[], warnings: LintResultRule[], state: LintFixState) => Promise<LintFixState>) | undefined;
|
|
33
33
|
protected addLintCriteriaMatch(apiCall: ApiCall, filepath: string): void;
|
|
34
34
|
getProductPaths(cacheKey: string, url: string): Promise<SwaggerFormat>;
|
|
35
|
+
getProductPathsFile(url: string): Promise<SwaggerFormat>;
|
|
35
36
|
private processPaths;
|
|
36
37
|
}
|
|
37
38
|
export {};
|
|
@@ -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;
|
|
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,uCAExG,GAAG,CAAC,MAAM,CAkBZ,CAAC;AAEF,eAAO,MAAM,qBAAqB,WACxB,cAAc,EAAE,YACd,cAAc,EAAE,SACnB,YAAY,KAClB,OAAO,CAAC,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;IAQhE,OAAO,CAAC,QAAQ;IAPjD,MAAM,CAAC,cAAc,SAAgC;IACrD,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;IA4CvC,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"}
|
|
@@ -8,6 +8,7 @@ const base_linter_1 = tslib_1.__importDefault(require("../../base-linter"));
|
|
|
8
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
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
11
12
|
exports.NON_FWD_SLASH_REGEX = '[^\\/\\s]*';
|
|
12
13
|
const CACHE_KEY = 'PERMISSIONS_LINTER';
|
|
13
14
|
const ONE_HOUR_MS = 1000 * 60 * 60;
|
|
@@ -30,13 +31,14 @@ exports.findMissingPermissions = (errors, warnings, permissionsType, state) => {
|
|
|
30
31
|
return missingPermissions;
|
|
31
32
|
};
|
|
32
33
|
exports.fixMissingPermissions = async (errors, warnings, state) => {
|
|
33
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
34
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
34
35
|
const missingScopes = exports.findMissingPermissions(errors, warnings, 'missingPermission', state);
|
|
35
36
|
const missingExternalFetchBackend = exports.findMissingPermissions(errors, warnings, 'missingExternalFetchPermission', state);
|
|
37
|
+
const missingContentStyle = exports.findMissingPermissions(errors, warnings, 'missingContentStylePermission', state);
|
|
36
38
|
const currentPermissions = (_b = (_a = (await state.configFile.readConfig())) === null || _a === void 0 ? void 0 : _a.permissions) !== null && _b !== void 0 ? _b : {};
|
|
37
39
|
const currentRemotes = (_d = (_c = (await state.configFile.readConfig())) === null || _c === void 0 ? void 0 : _c.remotes) !== null && _d !== void 0 ? _d : [];
|
|
38
40
|
const currentScopes = (_e = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.scopes) !== null && _e !== void 0 ? _e : [];
|
|
39
|
-
currentScopes.forEach(missingScopes.add
|
|
41
|
+
currentScopes.forEach((e) => missingScopes.add(e));
|
|
40
42
|
const currentExternalFetchBackend = (_h = (_g = (_f = currentPermissions === null || currentPermissions === void 0 ? void 0 : currentPermissions.external) === null || _f === void 0 ? void 0 : _f.fetch) === null || _g === void 0 ? void 0 : _g.backend) !== null && _h !== void 0 ? _h : [];
|
|
41
43
|
currentExternalFetchBackend
|
|
42
44
|
.map((item) => {
|
|
@@ -46,9 +48,12 @@ exports.fixMissingPermissions = async (errors, warnings, state) => {
|
|
|
46
48
|
return (_a = currentRemotes.find((remote) => remote.key == item.remote)) === null || _a === void 0 ? void 0 : _a.baseUrl;
|
|
47
49
|
})
|
|
48
50
|
.filter((item) => typeof item === 'string')
|
|
49
|
-
.forEach(missingExternalFetchBackend.add
|
|
51
|
+
.forEach((e) => missingExternalFetchBackend.add(e));
|
|
50
52
|
const arrayMissingExternalFetchBackend = [...missingExternalFetchBackend];
|
|
51
|
-
|
|
53
|
+
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 : [];
|
|
54
|
+
currentContentStyles.forEach((e) => missingContentStyle.add(e));
|
|
55
|
+
const arrayMissingContentStyles = [...missingContentStyle];
|
|
56
|
+
await state.configFile.writeToConfigFile('permissions', Object.assign(Object.assign(Object.assign(Object.assign({}, currentPermissions), { scopes: [...missingScopes] }), (arrayMissingExternalFetchBackend.length > 0
|
|
52
57
|
? {
|
|
53
58
|
external: currentPermissions.external
|
|
54
59
|
? Object.assign(Object.assign({}, currentPermissions.external), { fetch: currentPermissions.external.fetch
|
|
@@ -60,6 +65,13 @@ exports.fixMissingPermissions = async (errors, warnings, state) => {
|
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
}
|
|
68
|
+
: {})), (arrayMissingContentStyles.length > 0
|
|
69
|
+
? {
|
|
70
|
+
content: currentPermissions.content
|
|
71
|
+
? Object.assign(Object.assign({}, currentPermissions.content), { styles: arrayMissingContentStyles }) : {
|
|
72
|
+
styles: arrayMissingContentStyles
|
|
73
|
+
}
|
|
74
|
+
}
|
|
63
75
|
: {})));
|
|
64
76
|
return state;
|
|
65
77
|
};
|
|
@@ -70,10 +82,20 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
70
82
|
}
|
|
71
83
|
async bootstrap() {
|
|
72
84
|
this.cache = cli_shared_1.CachedConf.getCache(CACHE_KEY);
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
const LOCAL_CONF_SWAGGER = process.env.LOCAL_CONF_SWAGGER;
|
|
86
|
+
const LOCAL_JIRA_SWAGGER = process.env.LOCAL_JIRA_SWAGGER;
|
|
87
|
+
const USE_LOCAL_SWAGGER = process.env.USE_LOCAL_SWAGGER;
|
|
88
|
+
let swaggerFiles;
|
|
89
|
+
if (USE_LOCAL_SWAGGER && LOCAL_CONF_SWAGGER && LOCAL_JIRA_SWAGGER) {
|
|
90
|
+
swaggerFiles = [this.getProductPathsFile(LOCAL_JIRA_SWAGGER), this.getProductPathsFile(LOCAL_CONF_SWAGGER)];
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
swaggerFiles = [
|
|
94
|
+
this.getProductPaths(PermissionLinter.JIRA_CACHE_KEY, 'https://developer.atlassian.com/cloud/jira/platform/swagger-v3.v3.json'),
|
|
95
|
+
this.getProductPaths(PermissionLinter.CONFLUENCE_CACHE_KEY, 'https://developer.atlassian.com/cloud/confluence/swagger.v3.json')
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
const [jira, confluence] = await Promise.all(swaggerFiles);
|
|
77
99
|
this.jira = this.processPaths(jira.paths);
|
|
78
100
|
this.confluence = this.processPaths(confluence.paths);
|
|
79
101
|
this.nodeVisitors = [
|
|
@@ -139,6 +161,10 @@ class PermissionLinter extends base_linter_1.default {
|
|
|
139
161
|
}
|
|
140
162
|
return cached;
|
|
141
163
|
}
|
|
164
|
+
async getProductPathsFile(url) {
|
|
165
|
+
const response = fs_1.default.readFileSync(url);
|
|
166
|
+
return JSON.parse(response.toString());
|
|
167
|
+
}
|
|
142
168
|
processPaths(paths) {
|
|
143
169
|
const pathMap = new Map();
|
|
144
170
|
Object.keys(paths).forEach((path) => {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { LintClass, LintResultRule } from '../../../linter-interface';
|
|
2
2
|
import { BaseLintIssueVerifier, LintIssueVerifier } from '../../verifier-interface';
|
|
3
3
|
import { ContentPropertyApiCall } from '../api-call-interface';
|
|
4
|
-
|
|
4
|
+
declare type ContentPropertyPermissions = {
|
|
5
|
+
current: string[];
|
|
6
|
+
deprecated: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare const CONTENT_PROPERTY_PERMISSIONS_MAP: Record<string, Record<string, ContentPropertyPermissions>>;
|
|
5
9
|
export declare class ContentPropertyVerifier extends BaseLintIssueVerifier implements LintIssueVerifier<ContentPropertyApiCall[]> {
|
|
6
10
|
protected getLintClass(): LintClass;
|
|
7
11
|
process(apiCalls: ContentPropertyApiCall[]): Promise<LintResultRule[]>;
|
|
8
12
|
private getMissingScopes;
|
|
9
13
|
}
|
|
14
|
+
export {};
|
|
10
15
|
//# sourceMappingURL=content-property-verifier.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-property-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/content-property-verifier.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,
|
|
1
|
+
{"version":3,"file":"content-property-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/content-property-verifier.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,aAAK,0BAA0B,GAAG;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAyDvG,CAAC;AAEF,qBAAa,uBACX,SAAQ,qBACR,YAAW,iBAAiB,CAAC,sBAAsB,EAAE,CAAC;IACtD,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,QAAQ,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAuBnF,OAAO,CAAC,gBAAgB;CAyBzB"}
|
|
@@ -7,24 +7,60 @@ const text_1 = require("../../../text");
|
|
|
7
7
|
const verifier_interface_1 = require("../../verifier-interface");
|
|
8
8
|
exports.CONTENT_PROPERTY_PERMISSIONS_MAP = {
|
|
9
9
|
onJiraIssue: {
|
|
10
|
-
get:
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
get: {
|
|
11
|
+
current: ['read:issue.property:jira'],
|
|
12
|
+
deprecated: ['read:jira-work']
|
|
13
|
+
},
|
|
14
|
+
set: {
|
|
15
|
+
current: ['write:issue.property:jira'],
|
|
16
|
+
deprecated: ['write:jira-work']
|
|
17
|
+
},
|
|
18
|
+
delete: {
|
|
19
|
+
current: ['delete:issue.property:jira'],
|
|
20
|
+
deprecated: ['write:jira-work']
|
|
21
|
+
}
|
|
13
22
|
},
|
|
14
23
|
onJiraProject: {
|
|
15
|
-
get:
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
get: {
|
|
25
|
+
current: ['read:project.property:jira'],
|
|
26
|
+
deprecated: ['read:jira-work']
|
|
27
|
+
},
|
|
28
|
+
set: {
|
|
29
|
+
current: ['write:project.property:jira'],
|
|
30
|
+
deprecated: ['manage:jira-project']
|
|
31
|
+
},
|
|
32
|
+
delete: {
|
|
33
|
+
current: ['delete:project.property:jira'],
|
|
34
|
+
deprecated: ['manage:jira-project']
|
|
35
|
+
}
|
|
18
36
|
},
|
|
19
37
|
onConfluencePage: {
|
|
20
|
-
get:
|
|
21
|
-
|
|
22
|
-
|
|
38
|
+
get: {
|
|
39
|
+
current: ['read:content-details:confluence'],
|
|
40
|
+
deprecated: ['read:confluence-props']
|
|
41
|
+
},
|
|
42
|
+
set: {
|
|
43
|
+
current: ['read:content.property:confluence', 'write:content.property:confluence'],
|
|
44
|
+
deprecated: ['read:confluence-props', 'write:confluence-props']
|
|
45
|
+
},
|
|
46
|
+
delete: {
|
|
47
|
+
current: ['write:content.property:confluence'],
|
|
48
|
+
deprecated: ['write:confluence-props']
|
|
49
|
+
}
|
|
23
50
|
},
|
|
24
51
|
onConfluenceSpace: {
|
|
25
|
-
get:
|
|
26
|
-
|
|
27
|
-
|
|
52
|
+
get: {
|
|
53
|
+
current: ['read:content-details:confluence'],
|
|
54
|
+
deprecated: ['read:confluence-props']
|
|
55
|
+
},
|
|
56
|
+
set: {
|
|
57
|
+
current: ['read:space.property:confluence', 'write:space.property:confluence'],
|
|
58
|
+
deprecated: ['read:confluence-props', 'write:confluence-props']
|
|
59
|
+
},
|
|
60
|
+
delete: {
|
|
61
|
+
current: ['write:space.property:confluence'],
|
|
62
|
+
deprecated: ['write:confluence-props']
|
|
63
|
+
}
|
|
28
64
|
}
|
|
29
65
|
};
|
|
30
66
|
class ContentPropertyVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
@@ -50,10 +86,24 @@ class ContentPropertyVerifier extends verifier_interface_1.BaseLintIssueVerifier
|
|
|
50
86
|
getMissingScopes({ context, method }) {
|
|
51
87
|
var _a, _b;
|
|
52
88
|
const existingScopes = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.scopes;
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
89
|
+
const requiredScopesCurrent = exports.CONTENT_PROPERTY_PERMISSIONS_MAP[context][method]['current'];
|
|
90
|
+
const requiredScopesDeprecated = exports.CONTENT_PROPERTY_PERMISSIONS_MAP[context][method]['deprecated'];
|
|
91
|
+
const missingCurrentPerms = requiredScopesCurrent.filter((perm) => !(existingScopes === null || existingScopes === void 0 ? void 0 : existingScopes.includes(perm)));
|
|
92
|
+
if (missingCurrentPerms.length == 0)
|
|
93
|
+
return [];
|
|
94
|
+
let missingDeprecatedPerms = null;
|
|
95
|
+
if (requiredScopesDeprecated) {
|
|
96
|
+
missingDeprecatedPerms = requiredScopesDeprecated.filter((perm) => !(existingScopes === null || existingScopes === void 0 ? void 0 : existingScopes.includes(perm)));
|
|
97
|
+
if (missingDeprecatedPerms.length == 0)
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
if (missingCurrentPerms.length < requiredScopesCurrent.length) {
|
|
101
|
+
return missingCurrentPerms;
|
|
102
|
+
}
|
|
103
|
+
if (missingDeprecatedPerms && missingDeprecatedPerms.length < requiredScopesDeprecated.length) {
|
|
104
|
+
return missingDeprecatedPerms;
|
|
105
|
+
}
|
|
106
|
+
return requiredScopesCurrent;
|
|
57
107
|
}
|
|
58
108
|
}
|
|
59
109
|
exports.ContentPropertyVerifier = ContentPropertyVerifier;
|
|
@@ -2,6 +2,8 @@ import { LintResultRule, LintClass } from '../../../linter-interface';
|
|
|
2
2
|
import { ApiCall, ProductApiCall } from '../api-call-interface';
|
|
3
3
|
import { LintIssueVerifier, BaseLintIssueVerifier } from '../../verifier-interface';
|
|
4
4
|
import { ManifestSchema as Manifest } from '@forge/manifest';
|
|
5
|
+
import { Swagger } from 'atlassian-openapi';
|
|
6
|
+
import OAuth2ScopesWithState = Swagger.OAuth2ScopesWithState;
|
|
5
7
|
export interface ProductMethod {
|
|
6
8
|
originalPath: string;
|
|
7
9
|
methods: PathMethods;
|
|
@@ -9,6 +11,7 @@ export interface ProductMethod {
|
|
|
9
11
|
export interface PathMethods {
|
|
10
12
|
[method: string]: {
|
|
11
13
|
security: SecurityEntry[];
|
|
14
|
+
'x-atlassian-oauth2-scopes'?: OAuth2ScopesWithState[];
|
|
12
15
|
};
|
|
13
16
|
}
|
|
14
17
|
interface SecurityEntry {
|
|
@@ -24,6 +27,7 @@ export declare class ProductVerifier extends BaseLintIssueVerifier implements Li
|
|
|
24
27
|
private lookupApiCall;
|
|
25
28
|
private getMissingPermissionScopes;
|
|
26
29
|
private getRequiredScopes;
|
|
30
|
+
private getRequiredDeprecatedScopes;
|
|
27
31
|
}
|
|
28
32
|
export {};
|
|
29
33
|
//# sourceMappingURL=product-verifier.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/product-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"product-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/product-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,MAAM,EAAE,MAAM,GAAG;QAChB,QAAQ,EAAE,aAAa,EAAE,CAAC;QAC1B,2BAA2B,CAAC,EAAE,qBAAqB,EAAE,CAAC;KACvD,CAAC;CACH;AAED,UAAU,aAAa;IACrB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAED,oBAAY,uBAAuB,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAEjE,qBAAa,eAAgB,SAAQ,qBAAsB,YAAW,iBAAiB,CAAC,OAAO,EAAE,CAAC;IAI9F,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAHxB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,QAAQ,EACD,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,MAAM;IAKlC,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAoC3E,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,0BAA0B;IA8BlC,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,2BAA2B;CAWpC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ProductVerifier = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
4
5
|
const linter_interface_1 = require("../../../linter-interface");
|
|
5
6
|
const verifier_interface_1 = require("../../verifier-interface");
|
|
6
7
|
const cli_shared_1 = require("@forge/cli-shared");
|
|
7
8
|
const text_1 = require("../../../text");
|
|
9
|
+
const array_prototype_flatmap_1 = tslib_1.__importDefault(require("array.prototype.flatmap"));
|
|
8
10
|
class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
9
11
|
constructor(environment, manifest, pathMap, product) {
|
|
10
12
|
super(environment, manifest);
|
|
@@ -51,20 +53,46 @@ class ProductVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
|
51
53
|
}
|
|
52
54
|
getMissingPermissionScopes(apiCall) {
|
|
53
55
|
var _a, _b, _c;
|
|
54
|
-
const
|
|
56
|
+
const currentScopes = this.getRequiredScopes(apiCall);
|
|
57
|
+
const deprecatedScopes = this.getRequiredDeprecatedScopes(apiCall);
|
|
55
58
|
if (!((_c = (_b = (_a = this.manifest) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.scopes) === null || _c === void 0 ? void 0 : _c.length)) {
|
|
56
|
-
return
|
|
59
|
+
return currentScopes;
|
|
57
60
|
}
|
|
58
|
-
|
|
61
|
+
const missingCurrentScopes = currentScopes.filter((scope) => { var _a, _b; return !((_b = (_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.includes(scope)); });
|
|
62
|
+
if (!missingCurrentScopes.length)
|
|
63
|
+
return [];
|
|
64
|
+
const missingDeprecatedScopes = deprecatedScopes.filter((scope) => { var _a, _b; return !((_b = (_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.includes(scope)); });
|
|
65
|
+
if (deprecatedScopes.length && !missingDeprecatedScopes.length)
|
|
66
|
+
return [];
|
|
67
|
+
if (missingCurrentScopes.length < currentScopes.length) {
|
|
68
|
+
return missingCurrentScopes;
|
|
69
|
+
}
|
|
70
|
+
if (missingDeprecatedScopes.length < deprecatedScopes.length) {
|
|
71
|
+
return missingDeprecatedScopes;
|
|
72
|
+
}
|
|
73
|
+
return missingCurrentScopes;
|
|
59
74
|
}
|
|
60
75
|
getRequiredScopes({ regex, method }) {
|
|
61
|
-
var _a, _b;
|
|
76
|
+
var _a, _b, _c, _d;
|
|
62
77
|
if (!regex)
|
|
63
78
|
return [];
|
|
64
|
-
const
|
|
79
|
+
const oAuth2Scopes = (_b = (_a = this.pathMap.get(regex)) === null || _a === void 0 ? void 0 : _a.methods[method]) === null || _b === void 0 ? void 0 : _b['x-atlassian-oauth2-scopes'];
|
|
80
|
+
if (oAuth2Scopes) {
|
|
81
|
+
return array_prototype_flatmap_1.default(oAuth2Scopes.filter((scope) => scope.state === 'Current').map((scope) => scope.scopes), (x) => x);
|
|
82
|
+
}
|
|
83
|
+
const swaggerEntries = (_d = (_c = this.pathMap.get(regex)) === null || _c === void 0 ? void 0 : _c.methods[method]) === null || _d === void 0 ? void 0 : _d.security;
|
|
65
84
|
if (!swaggerEntries)
|
|
66
85
|
return [];
|
|
67
86
|
return swaggerEntries === null || swaggerEntries === void 0 ? void 0 : swaggerEntries.reduce((prev, curr) => [...prev, ...(curr['OAuth2'] || []), ...(curr['oAuthDefinitions'] || [])], []);
|
|
68
87
|
}
|
|
88
|
+
getRequiredDeprecatedScopes({ regex, method }) {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
if (!regex)
|
|
91
|
+
return [];
|
|
92
|
+
const oAuth2Scopes = (_b = (_a = this.pathMap.get(regex)) === null || _a === void 0 ? void 0 : _a.methods[method]) === null || _b === void 0 ? void 0 : _b['x-atlassian-oauth2-scopes'];
|
|
93
|
+
if (!oAuth2Scopes)
|
|
94
|
+
return [];
|
|
95
|
+
return array_prototype_flatmap_1.default(oAuth2Scopes.filter((scope) => scope.state === 'Deprecated').map((scope) => scope.scopes), (x) => x);
|
|
96
|
+
}
|
|
69
97
|
}
|
|
70
98
|
exports.ProductVerifier = ProductVerifier;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-hook-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/ui-hook-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ui-hook-verifier.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/verifiers/ui-hook-verifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AA2BpF,qBAAa,cAAe,SAAQ,qBAAsB,YAAW,iBAAiB,CAAC,OAAO,EAAE,CAAC;IAC/F,SAAS,CAAC,YAAY,IAAI,SAAS;IAItB,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAoC1E,OAAO,CAAC,WAAW;CAepB"}
|
|
@@ -5,9 +5,22 @@ const linter_interface_1 = require("../../../linter-interface");
|
|
|
5
5
|
const verifier_interface_1 = require("../../verifier-interface");
|
|
6
6
|
const text_1 = require("../../../text");
|
|
7
7
|
const FORGE_UI_HOOK_PERMISSIONS = {
|
|
8
|
-
useContentProperty:
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
useContentProperty: {
|
|
9
|
+
current: [
|
|
10
|
+
'read:content-details:confluence',
|
|
11
|
+
'read:content.property:confluence',
|
|
12
|
+
'write:content.property:confluence'
|
|
13
|
+
],
|
|
14
|
+
deprecated: ['read:confluence-props', 'write:confluence-props']
|
|
15
|
+
},
|
|
16
|
+
useSpaceProperty: {
|
|
17
|
+
current: ['read:content-details:confluence', 'read:space.property:confluence', 'write:space.property:confluence'],
|
|
18
|
+
deprecated: ['read:confluence-props', 'write:confluence-props']
|
|
19
|
+
},
|
|
20
|
+
useIssueProperty: {
|
|
21
|
+
current: ['read:issue.property:jira'],
|
|
22
|
+
deprecated: ['read:jira-work', 'write:jira-work']
|
|
23
|
+
}
|
|
11
24
|
};
|
|
12
25
|
class UIHookVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
13
26
|
getLintClass() {
|
|
@@ -15,17 +28,30 @@ class UIHookVerifier extends verifier_interface_1.BaseLintIssueVerifier {
|
|
|
15
28
|
}
|
|
16
29
|
async process(apiCalls) {
|
|
17
30
|
const rules = [];
|
|
18
|
-
|
|
31
|
+
for (const apiCall of apiCalls) {
|
|
19
32
|
const requiredPermissions = FORGE_UI_HOOK_PERMISSIONS[apiCall.hookName];
|
|
20
33
|
if (!requiredPermissions)
|
|
21
34
|
return rules;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
const { current, deprecated } = requiredPermissions;
|
|
36
|
+
const missingCurrentPerms = current.filter((perm) => { var _a, _b; return !((_b = (_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.includes(perm)); });
|
|
37
|
+
if (!missingCurrentPerms.length)
|
|
38
|
+
continue;
|
|
39
|
+
let missingDeprecatedPerms = null;
|
|
40
|
+
if (deprecated) {
|
|
41
|
+
missingDeprecatedPerms = deprecated.filter((perm) => { var _a, _b; return !((_b = (_a = this.manifest.permissions) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.includes(perm)); });
|
|
42
|
+
if (!missingDeprecatedPerms.length)
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (missingCurrentPerms.length < current.length) {
|
|
46
|
+
missingCurrentPerms.forEach((perm) => rules.push(this.getHookRule(apiCall, perm)));
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (deprecated && missingDeprecatedPerms && (missingDeprecatedPerms === null || missingDeprecatedPerms === void 0 ? void 0 : missingDeprecatedPerms.length) < deprecated.length) {
|
|
50
|
+
missingDeprecatedPerms.forEach((perm) => rules.push(this.getHookRule(apiCall, perm)));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
missingCurrentPerms.forEach((perm) => rules.push(this.getHookRule(apiCall, perm)));
|
|
54
|
+
}
|
|
29
55
|
return rules;
|
|
30
56
|
}
|
|
31
57
|
getHookRule(apiCall, permission) {
|
|
@@ -3,6 +3,7 @@ import { NodeVisitor } from '../../node-visitor-interface';
|
|
|
3
3
|
import { ApiCall } from '../api-call-interface';
|
|
4
4
|
export declare class ExternalApiCallVisitor implements NodeVisitor<ApiCall> {
|
|
5
5
|
visit(node: TSESTree.Node, parent: TSESTree.Node | undefined, callback: (fetchCall: ApiCall) => void): void;
|
|
6
|
+
private endpointCanBeChecked;
|
|
6
7
|
private transformArgsToFetchCall;
|
|
7
8
|
}
|
|
8
9
|
//# sourceMappingURL=external-fetch-call-visitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-fetch-call-visitor.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/external-fetch-call-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"external-fetch-call-visitor.d.ts","sourceRoot":"","sources":["../../../../../src/lint/linters/permission-linter/visitors/external-fetch-call-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAGhF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAE9D,qBAAa,sBAAuB,YAAW,WAAW,CAAC,OAAO,CAAC;IAC1D,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IA+ClH,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,wBAAwB,CAK7B;CACJ"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ExternalApiCallVisitor = void 0;
|
|
4
4
|
const typescript_estree_1 = require("@typescript-eslint/typescript-estree");
|
|
5
|
+
const url_1 = require("url");
|
|
5
6
|
const api_call_interface_1 = require("../api-call-interface");
|
|
6
7
|
class ExternalApiCallVisitor {
|
|
7
8
|
constructor() {
|
|
@@ -30,15 +31,29 @@ class ExternalApiCallVisitor {
|
|
|
30
31
|
node.property.name === 'fetch' &&
|
|
31
32
|
(parent === null || parent === void 0 ? void 0 : parent.type) === typescript_estree_1.AST_NODE_TYPES.CallExpression) {
|
|
32
33
|
const [endpointNode] = parent.arguments;
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
callback(fetchCall);
|
|
37
|
-
}
|
|
34
|
+
if (this.endpointCanBeChecked(endpointNode)) {
|
|
35
|
+
const fetchCall = this.transformArgsToFetchCall(endpointNode);
|
|
36
|
+
callback(fetchCall);
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
break;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
42
|
+
endpointCanBeChecked(endpointNode) {
|
|
43
|
+
const throws = (thunk) => {
|
|
44
|
+
try {
|
|
45
|
+
thunk();
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
catch (_a) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const isPathOnlyUrl = (s) => throws(() => new url_1.URL(s)) && !throws(() => new url_1.URL(s, 'http://example'));
|
|
53
|
+
return ((endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.type) === typescript_estree_1.AST_NODE_TYPES.Literal &&
|
|
54
|
+
typeof (endpointNode === null || endpointNode === void 0 ? void 0 : endpointNode.value) === 'string' &&
|
|
55
|
+
endpointNode.value.trim() !== '' &&
|
|
56
|
+
!isPathOnlyUrl(endpointNode.value));
|
|
57
|
+
}
|
|
43
58
|
}
|
|
44
59
|
exports.ExternalApiCallVisitor = ExternalApiCallVisitor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/lint",
|
|
3
|
-
"version": "0.0.0-experimental-
|
|
3
|
+
"version": "0.0.0-experimental-c3d0263",
|
|
4
4
|
"description": "Linting for forge apps",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -11,15 +11,16 @@
|
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@types/cross-spawn": "^6.0.1",
|
|
14
|
-
"@types/eslint": "
|
|
14
|
+
"@types/eslint": "8.2.2",
|
|
15
15
|
"@types/node-fetch": "^2.5.7"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@forge/cli-shared": "0.0.0-experimental-
|
|
19
|
-
"@forge/csp": "
|
|
20
|
-
"@forge/manifest": "0.0.0-experimental-
|
|
18
|
+
"@forge/cli-shared": "0.0.0-experimental-c3d0263",
|
|
19
|
+
"@forge/csp": "0.0.0-experimental-c3d0263",
|
|
20
|
+
"@forge/manifest": "0.0.0-experimental-c3d0263",
|
|
21
21
|
"@typescript-eslint/typescript-estree": "^3.5.0",
|
|
22
22
|
"cross-spawn": "^7.0.1",
|
|
23
|
-
"node-fetch": "
|
|
23
|
+
"node-fetch": "2.6.1",
|
|
24
|
+
"atlassian-openapi": "^1.0.13"
|
|
24
25
|
}
|
|
25
26
|
}
|