From fa47fee55e43052a9c544e10ff13dd2282380297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 11 Jan 2023 10:48:27 +0100 Subject: [PATCH] feat: RBAC read params from body (#2846) ## About the changes This is a follow-up on #1953 This implementation generalizes how we fetch some standard parameters from the query parameters or request body. ## Discussion points Unfortunately, we have not used standard names for our APIs and one example is our `projectId` (in some cases we just used `project`). Ideally, we're only using one way of sending these parameters either `projectId` or `project` (same applies to `environment` vs `environmentId`). If both parameters are present, due to historical reasons, we'll give precedence to: - `projectId` over `project` - `environment` over `environmentId` In the presence of both query parameters and body, we'll give precedence to query parameters also for historical reasons. --- src/lib/middleware/rbac-middleware.ts | 28 ++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/lib/middleware/rbac-middleware.ts b/src/lib/middleware/rbac-middleware.ts index 081dda3c1f..4c20d8240c 100644 --- a/src/lib/middleware/rbac-middleware.ts +++ b/src/lib/middleware/rbac-middleware.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import { CREATE_FEATURE, DELETE_FEATURE, @@ -18,6 +17,18 @@ interface PermissionChecker { ): Promise; } +function findParam( + name: string, + { params, body }: any, + defaultValue?: string, +): string | undefined { + let found = params ? params[name] : undefined; + if (found === undefined) { + found = body ? body[name] : undefined; + } + return found || defaultValue; +} + const rbacMiddleware = ( config: Pick, { featureToggleStore }: Pick, @@ -44,16 +55,23 @@ const rbacMiddleware = ( return false; } - // For /api/admin/projects/:projectId we will find it as part of params - let { projectId, environment } = params; + let projectId = + findParam('projectId', req) || findParam('project', req); + let environment = + findParam('environment', req) || + findParam('environmentId', req); // Temporary workaround to figure out projectId for feature toggle updates. // will be removed in Unleash v5.0 if ([DELETE_FEATURE, UPDATE_FEATURE].includes(permission)) { const { featureName } = params; projectId = await featureToggleStore.getProjectId(featureName); - } else if (permission === CREATE_FEATURE) { - projectId = projectId || req.body.project || 'default'; + } else if ( + projectId === undefined && + (permission == CREATE_FEATURE || + permission.endsWith('FEATURE_STRATEGY')) + ) { + projectId = 'default'; } return accessService.hasPermission(