]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21109 - Fix permission issue on api/project_links/delete endpoint
authorantoine.vinot <antoine.vinot@sonarsource.com>
Wed, 29 Nov 2023 11:29:14 +0000 (12:29 +0100)
committersonartech <sonartech@sonarsource.com>
Fri, 1 Dec 2023 20:02:43 +0000 (20:02 +0000)
server/sonar-webserver-webapi/src/it/java/org/sonar/server/projectlink/ws/DeleteActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectlink/ws/DeleteAction.java

index 303237ba097e0d5e4f55cf1fbea9358c8b468000..7942433a0f4691eff0315542bfe3ecb27da7cc07 100644 (file)
@@ -27,11 +27,14 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ProjectLinkDto;
+import org.sonar.db.permission.GlobalPermission;
 import org.sonar.db.project.ProjectDto;
+import org.sonar.server.component.TestComponentFinder;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
 import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
 
@@ -49,7 +52,7 @@ public class DeleteActionIT {
 
   private final DbClient dbClient = db.getDbClient();
   private final DbSession dbSession = db.getSession();
-  private final WsActionTester ws = new WsActionTester(new DeleteAction(dbClient, userSession));
+  private final WsActionTester ws = new WsActionTester(new DeleteAction(dbClient, userSession, TestComponentFinder.from(db)));
 
   @Test
   public void no_response() {
@@ -74,6 +77,17 @@ public class DeleteActionIT {
     assertLinkIsDeleted(link.getUuid());
   }
 
+  @Test
+  public void delete_whenGlobalAdminPermission_shouldDeleteLink() {
+    ProjectDto project = db.components().insertPrivateProject().getProjectDto();
+    ProjectLinkDto link = db.projectLinks().insertCustomLink(project);
+    userSession.logIn().addPermission(GlobalPermission.ADMINISTER);
+
+    deleteLink(link);
+
+    assertLinkIsDeleted(link.getUuid());
+  }
+
   @Test
   public void keep_links_of_another_project() {
     ProjectDto project1 = db.components().insertPrivateProject().getProjectDto();
@@ -101,11 +115,11 @@ public class DeleteActionIT {
 
   @Test
   public void fail_on_unknown_link() {
-    assertThatThrownBy(() -> ws.newRequest()
+    TestRequest testRequest = ws.newRequest()
       .setMethod("POST")
-      .setParam(PARAM_ID, "UNKNOWN")
-      .execute())
-        .isInstanceOf(NotFoundException.class);
+      .setParam(PARAM_ID, "UNKNOWN");
+    assertThatThrownBy(testRequest::execute)
+      .isInstanceOf(NotFoundException.class);
   }
 
   @Test
index ee2b0a5cd53aa25d2965577a5a8399d1800efca3..8d1a94e733f7f8d83c31aab35266548fb75ec24e 100644 (file)
@@ -26,21 +26,27 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ProjectLinkDto;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 
 import static org.sonar.db.component.ProjectLinkDto.PROVIDED_TYPES;
+import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
 import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.ACTION_DELETE;
 import static org.sonar.server.projectlink.ws.ProjectLinksWsParameters.PARAM_ID;
 
 public class DeleteAction implements ProjectLinksWsAction {
   private final DbClient dbClient;
   private final UserSession userSession;
+  private final ComponentFinder componentFinder;
 
-  public DeleteAction(DbClient dbClient, UserSession userSession) {
+  public DeleteAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
     this.dbClient = dbClient;
     this.userSession = userSession;
+    this.componentFinder = componentFinder;
   }
 
   @Override
@@ -70,7 +76,9 @@ public class DeleteAction implements ProjectLinksWsAction {
       ProjectLinkDto link = dbClient.projectLinkDao().selectByUuid(dbSession, id);
 
       link = NotFoundException.checkFound(link, "Link with id '%s' not found", id);
-      checkProjectAdminPermission(link);
+      componentFinder.getProjectByUuidOrKey(dbSession, link.getProjectUuid(), null, PROJECT_ID_AND_KEY);
+      ProjectDto projectDto = componentFinder.getProjectByUuidOrKey(dbSession, link.getProjectUuid(), null, PROJECT_ID_AND_KEY);
+      checkProjectAdminPermission(projectDto);
       checkNotProvided(link);
 
       dbClient.projectLinkDao().delete(dbSession, link.getUuid());
@@ -78,13 +86,16 @@ public class DeleteAction implements ProjectLinksWsAction {
     }
   }
 
+  private void checkProjectAdminPermission(ProjectDto projectDto) {
+    if (userSession.hasPermission(GlobalPermission.ADMINISTER)) {
+      return;
+    }
+    userSession.checkEntityPermission(UserRole.ADMIN, projectDto);
+  }
+
   private static void checkNotProvided(ProjectLinkDto link) {
     String type = link.getType();
     boolean isProvided = type != null && PROVIDED_TYPES.contains(type);
     BadRequestException.checkRequest(!isProvided, "Provided link cannot be deleted.");
   }
-
-  private void checkProjectAdminPermission(ProjectLinkDto link) {
-    userSession.checkComponentUuidPermission(UserRole.ADMIN, link.getProjectUuid());
-  }
 }