From c5afa8ff11f66c452bbcf9708d157cc865f36f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Mon, 22 Jan 2024 12:50:14 +0100 Subject: [PATCH] fix: unauthorized disable feature (#5982) ## About the changes This was spotted while testing automated actions. Steps to reproduce: 1. Add an editor user 2. Get a PAT for the editor user 3. As Admin create a feature in a project where the editor user is not a member and enable the feature 4. Try using the editor's PAT to modify the feature 5. As the editor create a project (you'd be made owner) and try the same request but just change the project name for the new project just created (don't change anything else) **Expected behavior**: you can't disable the feature **Actual behavior**: the feature is disabled This does not happen when trying to turn on a flag because during the turn-on process we do validate if the feature belongs to project when we call updateStrategy: https://github.com/Unleash/unleash/blob/c18a7c0dc226f6b32a601a8d002dcd8f94d3c9af/src/lib/features/feature-toggle/feature-toggle-service.ts#L1751-L1764 --- src/lib/features/feature-toggle/feature-toggle-service.ts | 4 ++++ src/lib/services/access-service.ts | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/features/feature-toggle/feature-toggle-service.ts b/src/lib/features/feature-toggle/feature-toggle-service.ts index 226a2dd6b3..76bad81cd1 100644 --- a/src/lib/features/feature-toggle/feature-toggle-service.ts +++ b/src/lib/features/feature-toggle/feature-toggle-service.ts @@ -1732,6 +1732,10 @@ class FeatureToggleService { user?: IUser, shouldActivateDisabledStrategies = false, ): Promise { + await this.validateFeatureBelongsToProject({ + featureName, + projectId: project, + }); const hasEnvironment = await this.featureEnvironmentStore.featureHasEnvironment( environment, diff --git a/src/lib/services/access-service.ts b/src/lib/services/access-service.ts index 2c5d689c62..41911be292 100644 --- a/src/lib/services/access-service.ts +++ b/src/lib/services/access-service.ts @@ -65,6 +65,9 @@ export type IdPermissionRef = Pick; export type NamePermissionRef = Pick; export type PermissionRef = IdPermissionRef | NamePermissionRef; +type APIUser = Pick & { isAPI: true }; +type NonAPIUser = Pick & { isAPI?: false }; + export interface IRoleCreation { name: string; description: string; @@ -150,7 +153,7 @@ export class AccessService { * @param projectId */ async hasPermission( - user: Pick, + user: APIUser | NonAPIUser, permission: string | string[], projectId?: string, environment?: string, @@ -198,7 +201,7 @@ export class AccessService { } async getPermissionsForUser( - user: Pick, + user: APIUser | NonAPIUser, ): Promise { if (user.isAPI) { return user.permissions?.map((p) => ({