From 4fa96203cbb933c13fa2799c277b3ca21c8cb15e Mon Sep 17 00:00:00 2001 From: Mara Jochum Date: Thu, 15 Sep 2022 16:54:56 +0200 Subject: [PATCH] Added sample cds rule --- .eslint/index.js | 15 +++++++++ .eslint/package.json | 4 +++ .eslint/rules/no-open-services.js | 38 ++++++++++++++++++++++ .eslintrc | 53 +++++++++++++++++-------------- .vscode/settings.json | 10 +++++- package.json | 7 ++-- 6 files changed, 101 insertions(+), 26 deletions(-) create mode 100644 .eslint/index.js create mode 100644 .eslint/package.json create mode 100644 .eslint/rules/no-open-services.js diff --git a/.eslint/index.js b/.eslint/index.js new file mode 100644 index 00000000..e6aeed89 --- /dev/null +++ b/.eslint/index.js @@ -0,0 +1,15 @@ +const cds = require("@sap/eslint-plugin-cds"); + +module.exports = { + configs: { + recommended: { + plugins: ["cloud-cap-samples"], + rules: { + "cloud-cap-samples/no-open-services": ["error", "show"] + } + } + }, + rules: { + "no-open-services": cds.createRule(require("./rules/no-open-services")), + } +}; diff --git a/.eslint/package.json b/.eslint/package.json new file mode 100644 index 00000000..c641a553 --- /dev/null +++ b/.eslint/package.json @@ -0,0 +1,4 @@ +{ + "name": "eslint-plugin-cloud-cap-samples", + "version": "1.0.0" +} diff --git a/.eslint/rules/no-open-services.js b/.eslint/rules/no-open-services.js new file mode 100644 index 00000000..880d20cb --- /dev/null +++ b/.eslint/rules/no-open-services.js @@ -0,0 +1,38 @@ +module.exports = { + meta: { + docs: { + description: "Service without `@requires/restrict` should not expose fields `createdBy` and `modifiedBy`.", + version: "1.0.0" + }, + fixable: "code", + model: "inferred" + }, + create: function (context) { + return { entity: checkForExposedFields }; + + function checkForExposedFields(e) { + const services = context.getModel().services; + const unauthorizedServices = services + .map((s) => { + if (!s["@requires"] && !s["@restrict"]) { + return s.name; + } + }) + .filter((item) => !!item); + const found = Object.keys(e.elements).find((r) => ["createdBy", "modifiedBy"].indexOf(r) >= 0); + const isUnauthorizedService = unauthorizedServices.some((r) => { + if (e.name.includes(r)) { + return true; + } + return false; + }); + if (found && isUnauthorizedService) { + context.report({ + message: `Danger - exposed field '${found}' with '${e.name}' Either remove these or add add \`@restrict/requires\`.`, + node: context.getNode(e), + file: e.$location.file + }); + } + } + } + }; diff --git a/.eslintrc b/.eslintrc index aaf7f04f..d8e10161 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,25 +1,32 @@ { - "extends": "eslint:recommended", - "env": { - "browser": true, - "es2022": true, - "node": true, - "jest": true, - "mocha": true - }, - "globals": { - "SELECT": true, - "INSERT": true, - "UPDATE": true, - "DELETE": true, - "CREATE": true, - "DROP": true, - "cds": true - }, - "rules": { - "no-console": "off", - "require-atomic-updates": "off", - "require-await":"warn", - "no-unused-vars": ["warn", { "argsIgnorePattern": "_" }] - } + "extends": [ + "eslint:recommended", + "plugin:@sap/cds/recommended", + "plugin:cloud-cap-samples/recommended" + ], + "plugins": [ + "cloud-cap-samples" + ], + "env": { + "browser": true, + "es2022": true, + "node": true, + "jest": true, + "mocha": true + }, + "globals": { + "SELECT": true, + "INSERT": true, + "UPDATE": true, + "DELETE": true, + "CREATE": true, + "DROP": true, + "cds": true + }, + "rules": { + "no-console": "off", + "require-atomic-updates": "off", + "require-await":"warn", + "no-unused-vars": ["warn", { "argsIgnorePattern": "_" }] + } } diff --git a/.vscode/settings.json b/.vscode/settings.json index 70b6c043..bf4970b0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,5 +14,13 @@ "**/odata-v4/okra/**" ] }, - "mochaExplorer.parallel": true + "mochaExplorer.parallel": true, + "eslint.validate": [ + "cds", + "csn", + "csv", + "csv (semicolon)", + "tsv", + "tab" + ] } diff --git a/package.json b/package.json index 88bb15bc..4a91c75b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "repository": "https://github.com/sap-samples/cloud-cap-samples.git", "author": "daniel.hutzel@sap.com", "dependencies": { - "@sap/cds": ">=5.5.3" + "@sap/cds": ">=5.5.3", + "@sap/eslint-plugin-cds": "file:../../SAPDevelop/CAP/Tools/dev/cds-lint", + "eslint-plugin-cloud-cap-samples": "file:.eslint" }, "workspaces": [ "./*/" @@ -16,7 +18,8 @@ "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", "semver": "^7", - "sqlite3": "^5" + "sqlite3": "^5", + "eslint": "^7" }, "scripts": { "cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",