From 8685abf99e94ab7fa82716f06fbd25769e55ec20 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 22 Feb 2022 18:40:09 +0000 Subject: [PATCH] Refactoring how endpoints are specified so that the middlewares can be applied in a more generic fashion. --- .../backend-core/src/security/permissions.js | 1 + .../server/src/api/controllers/public/rows.js | 1 - .../src/api/routes/public/applications.js | 17 +++--- .../server/src/api/routes/public/index.js | 59 +++++++++++++++---- .../server/src/api/routes/public/queries.js | 11 ++-- packages/server/src/api/routes/public/rows.js | 45 ++++---------- .../server/src/api/routes/public/tables.js | 17 +++--- .../server/src/api/routes/public/users.js | 17 +++--- .../src/api/routes/public/utils/Endpoint.js | 23 ++++++++ 9 files changed, 115 insertions(+), 76 deletions(-) create mode 100644 packages/server/src/api/routes/public/utils/Endpoint.js diff --git a/packages/backend-core/src/security/permissions.js b/packages/backend-core/src/security/permissions.js index 3b05c10e20..28044a5129 100644 --- a/packages/backend-core/src/security/permissions.js +++ b/packages/backend-core/src/security/permissions.js @@ -10,6 +10,7 @@ const PermissionLevels = { // these are the global types, that govern the underlying default behaviour const PermissionTypes = { + APP: "app", TABLE: "table", USER: "user", AUTOMATION: "automation", diff --git a/packages/server/src/api/controllers/public/rows.js b/packages/server/src/api/controllers/public/rows.js index 3c5e8e677c..f0d6577162 100644 --- a/packages/server/src/api/controllers/public/rows.js +++ b/packages/server/src/api/controllers/public/rows.js @@ -20,7 +20,6 @@ function fixRow(row, params) { exports.search = async ctx => { await rowController.search(ctx) - console.log(ctx.body) } exports.create = ctx => { diff --git a/packages/server/src/api/routes/public/applications.js b/packages/server/src/api/routes/public/applications.js index 41b2f52798..efcff45945 100644 --- a/packages/server/src/api/routes/public/applications.js +++ b/packages/server/src/api/routes/public/applications.js @@ -1,7 +1,8 @@ -const Router = require("@koa/router") const controller = require("../../controllers/public/applications") +const Endpoint = require("./utils/Endpoint") -const router = Router() +const read = [], + write = [] /** * @openapi @@ -34,7 +35,7 @@ const router = Router() * applications: * $ref: '#/components/examples/applications' */ -router.post("/applications/search", controller.search) +read.push(new Endpoint("post", "/applications/search", controller.search)) /** * @openapi @@ -62,7 +63,7 @@ router.post("/applications/search", controller.search) * application: * $ref: '#/components/examples/application' */ -router.post("/applications", controller.create) +write.push(new Endpoint("post", "/applications", controller.create)) /** * @openapi @@ -90,7 +91,7 @@ router.post("/applications", controller.create) * application: * $ref: '#/components/examples/application' */ -router.put("/applications/:appId", controller.update) +write.push(new Endpoint("put", "/applications/:appId", controller.update)) /** * @openapi @@ -112,7 +113,7 @@ router.put("/applications/:appId", controller.update) * application: * $ref: '#/components/examples/application' */ -router.delete("/applications/:appId", controller.delete) +write.push(new Endpoint("delete", "/applications/:appId", controller.delete)) /** * @openapi @@ -134,6 +135,6 @@ router.delete("/applications/:appId", controller.delete) * application: * $ref: '#/components/examples/application' */ -router.get("/applications/:appId", controller.read) +read.push(new Endpoint("get", "/applications/:appId", controller.read)) -module.exports = router +module.exports = { read, write } diff --git a/packages/server/src/api/routes/public/index.js b/packages/server/src/api/routes/public/index.js index e52c9f8291..1ec311b855 100644 --- a/packages/server/src/api/routes/public/index.js +++ b/packages/server/src/api/routes/public/index.js @@ -1,22 +1,55 @@ -const appRoute = require("./applications") -const queryRoute = require("./queries") -const tableRoute = require("./tables") -const rowRoute = require("./rows") -const userRoute = require("./users") +const appEndpoints = require("./applications") +const queryEndpoints = require("./queries") +const tableEndpoints = require("./tables") +const rowEndpoints = require("./rows") +const userEndpoints = require("./users") const Router = require("@koa/router") const usage = require("../../../middleware/usageQuota") +const authorized = require("../../../middleware/authorized") +const { + paramResource, + paramSubResource, +} = require("../../../middleware/resourceId") +const { + PermissionLevels, + PermissionTypes, +} = require("@budibase/backend-core/permissions") const PREFIX = "/api/public/v1" -const ROUTES = [appRoute, queryRoute, tableRoute, rowRoute, userRoute] -const router = new Router({ +const publicRouter = new Router({ prefix: PREFIX, }) -for (let route of ROUTES) { - // apply usage to everything, middleware will work out whats needs it - route.use(usage) - router.use(route.routes()) - router.use(route.allowedMethods()) + +function addMiddleware(endpoints, middleware) { + for (let endpoint of endpoints) { + endpoint.addMiddleware(middleware) + } } -module.exports = router +function addToRouter(endpoints) { + for (let endpoint of endpoints) { + endpoint.apply(publicRouter) + } +} + +function applyRoutes(endpoints, permType, resource, subResource = null) { + const paramMiddleware = subResource + ? paramSubResource(resource, subResource) + : paramResource(resource) + addMiddleware(endpoints.read, paramMiddleware) + addMiddleware(endpoints.write, paramMiddleware) + addMiddleware(endpoints.read, authorized(permType, PermissionLevels.READ)) + addMiddleware(endpoints.write, authorized(permType, PermissionLevels.WRITE)) + addMiddleware(endpoints.write, usage) + addToRouter(endpoints.read) + addToRouter(endpoints.write) +} + +applyRoutes(rowEndpoints, PermissionTypes.TABLE, "tableId", "rowId") +applyRoutes(appEndpoints, PermissionTypes.APP, "appId") +applyRoutes(tableEndpoints, PermissionTypes.TABLE, "tableId") +applyRoutes(userEndpoints, PermissionTypes.USER, "userId") +applyRoutes(queryEndpoints, PermissionTypes.QUERY, "queryId") + +module.exports = publicRouter diff --git a/packages/server/src/api/routes/public/queries.js b/packages/server/src/api/routes/public/queries.js index 220346f58a..b44edf9b44 100644 --- a/packages/server/src/api/routes/public/queries.js +++ b/packages/server/src/api/routes/public/queries.js @@ -1,7 +1,8 @@ -const Router = require("@koa/router") const controller = require("../../controllers/public/queries") +const Endpoint = require("./utils/Endpoint") -const router = Router() +const read = [], + write = [] /** * @openapi @@ -34,7 +35,7 @@ const router = Router() * queries: * $ref: '#/components/examples/queries' */ -router.post("/queries/search", controller.search) +read.push(new Endpoint("post", "/queries/search", controller.search)) /** * @openapi @@ -59,6 +60,6 @@ router.post("/queries/search", controller.search) * query: * $ref: '#/components/examples/query' */ -router.post("/queries/:queryId", controller.execute) +write.push(new Endpoint("post", "/queries/:queryId", controller.execute)) -module.exports = router +module.exports = { read, write } diff --git a/packages/server/src/api/routes/public/rows.js b/packages/server/src/api/routes/public/rows.js index 45d9f25027..e5214a1959 100644 --- a/packages/server/src/api/routes/public/rows.js +++ b/packages/server/src/api/routes/public/rows.js @@ -1,15 +1,8 @@ -const Router = require("@koa/router") const controller = require("../../controllers/public/rows") -const authorized = require("../../../middleware/authorized") -const { paramSubResource } = require("../../../middleware/resourceId") -const { - PermissionLevels, - PermissionTypes, -} = require("@budibase/backend-core/permissions") +const Endpoint = require("./utils/Endpoint") -const router = Router() - -router.use(paramSubResource("tableId", "rowId")) +const read = [], + write = [] /** * @openapi @@ -127,10 +120,8 @@ router.use(paramSubResource("tableId", "rowId")) * search: * $ref: '#/components/examples/rows' */ -router.post( - "/tables/:tableId/rows/search", - authorized(PermissionTypes.TABLE, PermissionLevels.READ), - controller.search +read.push( + new Endpoint("post", "/tables/:tableId/rows/search", controller.search) ) /** @@ -164,11 +155,7 @@ router.post( * row: * $ref: '#/components/examples/row' */ -router.post( - "/tables/:tableId/rows", - authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), - controller.create -) +write.push(new Endpoint("post", "/tables/:tableId/rows", controller.create)) /** * @openapi @@ -201,10 +188,8 @@ router.post( * row: * $ref: '#/components/examples/row' */ -router.put( - "/tables/:tableId/rows/:rowId", - authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), - controller.update +write.push( + new Endpoint("put", "/tables/:tableId/rows/:rowId", controller.update) ) /** @@ -229,10 +214,8 @@ router.put( * row: * $ref: '#/components/examples/row' */ -router.delete( - "/tables/:tableId/rows/:rowId", - authorized(PermissionTypes.TABLE, PermissionLevels.WRITE), - controller.delete +write.push( + new Endpoint("delete", "/tables/:tableId/rows/:rowId", controller.delete) ) /** @@ -257,10 +240,6 @@ router.delete( * row: * $ref: '#/components/examples/row' */ -router.get( - "/tables/:tableId/rows/:rowId", - authorized(PermissionTypes.TABLE, PermissionLevels.READ), - controller.read -) +read.push(new Endpoint("get", "/tables/:tableId/rows/:rowId", controller.read)) -module.exports = router +module.exports = { read, write } diff --git a/packages/server/src/api/routes/public/tables.js b/packages/server/src/api/routes/public/tables.js index 0c2684b80c..bb875cad1b 100644 --- a/packages/server/src/api/routes/public/tables.js +++ b/packages/server/src/api/routes/public/tables.js @@ -1,7 +1,8 @@ -const Router = require("@koa/router") const controller = require("../../controllers/public/tables") +const Endpoint = require("./utils/Endpoint") -const router = Router() +const read = [], + write = [] /** * @openapi @@ -34,7 +35,7 @@ const router = Router() * tables: * $ref: '#/components/examples/tables' */ -router.post("/tables/search", controller.search) +read.push(new Endpoint("post", "/tables/search", controller.search)) /** * @openapi @@ -65,7 +66,7 @@ router.post("/tables/search", controller.search) * table: * $ref: '#/components/examples/table' */ -router.post("/tables", controller.create) +write.push(new Endpoint("post", "/tables", controller.create)) /** * @openapi @@ -96,7 +97,7 @@ router.post("/tables", controller.create) * table: * $ref: '#/components/examples/table' */ -router.put("/tables/:tableId", controller.update) +write.push(new Endpoint("put", "/tables/:tableId", controller.update)) /** * @openapi @@ -119,7 +120,7 @@ router.put("/tables/:tableId", controller.update) * table: * $ref: '#/components/examples/table' */ -router.delete("/tables/:tableId", controller.delete) +write.push(new Endpoint("delete", "/tables/:tableId", controller.delete)) /** * @openapi @@ -142,6 +143,6 @@ router.delete("/tables/:tableId", controller.delete) * table: * $ref: '#/components/examples/table' */ -router.get("/tables/:tableId", controller.read) +read.push(new Endpoint("get", "/tables/:tableId", controller.read)) -module.exports = router +module.exports = { read, write } diff --git a/packages/server/src/api/routes/public/users.js b/packages/server/src/api/routes/public/users.js index 0745d65e16..05d563bde2 100644 --- a/packages/server/src/api/routes/public/users.js +++ b/packages/server/src/api/routes/public/users.js @@ -1,7 +1,8 @@ -const Router = require("@koa/router") const controller = require("../../controllers/public/users") +const Endpoint = require("./utils/Endpoint") -const router = Router() +const read = [], + write = [] /** * @openapi @@ -31,7 +32,7 @@ const router = Router() * users: * $ref: '#/components/examples/users' */ -router.post("/users/search", controller.search) +read.push(new Endpoint("post", "/users/search", controller.search)) /** * @openapi @@ -59,7 +60,7 @@ router.post("/users/search", controller.search) * user: * $ref: '#/components/examples/user' */ -router.post("/users", controller.create) +write.push(new Endpoint("post", "/users", controller.create)) /** * @openapi @@ -88,7 +89,7 @@ router.post("/users", controller.create) * user: * $ref: '#/components/examples/user' */ -router.put("/users/:userId", controller.update) +write.push(new Endpoint("put", "/users/:userId", controller.update)) /** * @openapi @@ -111,7 +112,7 @@ router.put("/users/:userId", controller.update) * user: * $ref: '#/components/examples/user' */ -router.delete("/users/:userId", controller.delete) +write.push(new Endpoint("delete", "/users/:userId", controller.delete)) /** * @openapi @@ -134,6 +135,6 @@ router.delete("/users/:userId", controller.delete) * user: * $ref: '#/components/examples/user' */ -router.get("/users/:userId", controller.read) +read.push(new Endpoint("get", "/users/:userId", controller.read)) -module.exports = router +module.exports = { read, write } diff --git a/packages/server/src/api/routes/public/utils/Endpoint.js b/packages/server/src/api/routes/public/utils/Endpoint.js new file mode 100644 index 0000000000..a026d3db2a --- /dev/null +++ b/packages/server/src/api/routes/public/utils/Endpoint.js @@ -0,0 +1,23 @@ +class Endpoint { + constructor(method, url, controller) { + this.method = method + this.url = url + this.controller = controller + this.middlewares = [] + } + + addMiddleware(middleware) { + this.middlewares.push(middleware) + } + + apply(router) { + const method = this.method, + url = this.url + const middlewares = this.middlewares, + controller = this.controller + const params = [url, ...middlewares, controller] + router[method](...params) + } +} + +module.exports = Endpoint