]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18525 Support of PUT verb for /api/scim/v2/Groups/{groupId}
authorWojtek Wajerowicz <115081248+wojciech-wajerowicz-sonarsource@users.noreply.github.com>
Tue, 28 Feb 2023 13:23:13 +0000 (14:23 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 22 Mar 2023 20:04:06 +0000 (20:04 +0000)
server/sonar-webserver-webapi/src/it/java/org/sonar/server/usergroups/ws/UpdateActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/GroupWsSupport.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/UpdateAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/usergroups/ws/GroupWsSupportTest.java [new file with mode: 0644]

index c0e9c08e7f431d13d941032f35ddec76e306fd4e..ff80fb8c4c625d9f409819df92bb745ac8b59395 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
@@ -176,7 +177,7 @@ public class UpdateActionIT {
       .setParam(PARAM_GROUP_NAME, "");
 
     assertThatThrownBy(request::execute)
-      .isInstanceOf(IllegalArgumentException.class)
+      .isInstanceOf(BadRequestException.class)
       .hasMessage("Group name cannot be empty");
   }
 
@@ -201,7 +202,7 @@ public class UpdateActionIT {
       .setParam(PARAM_GROUP_NAME, "AnYoNe");
 
     assertThatThrownBy(request::execute)
-      .isInstanceOf(IllegalArgumentException.class)
+      .isInstanceOf(BadRequestException.class)
       .hasMessage("Anyone group cannot be used");
   }
 
index b330843613e754b2985192350b42ff5e4c34a571..05c66b474ec9c338c736fc13414f341be10fbb20 100644 (file)
 package org.sonar.server.usergroups.ws;
 
 import java.util.Optional;
+import javax.annotation.Nullable;
 import org.sonar.api.security.DefaultGroups;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.api.user.UserGroupValidation;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.user.GroupDto;
+import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.permission.GroupUuid;
 import org.sonar.server.permission.GroupUuidOrAnyone;
@@ -95,6 +98,39 @@ public class GroupWsSupport {
     return GroupUuidOrAnyone.from(group.get());
   }
 
+  public GroupDto updateGroup(DbSession dbSession, GroupDto group, @Nullable String newName) {
+    checkGroupIsNotDefault(dbSession, group);
+    return updateName(dbSession, group, newName);
+  }
+
+  public GroupDto updateGroup(DbSession dbSession, GroupDto group, @Nullable String newName, @Nullable String newDescription) {
+    checkGroupIsNotDefault(dbSession, group);
+    GroupDto withUpdatedName = updateName(dbSession, group, newName);
+    return updateDescription(dbSession, withUpdatedName, newDescription);
+  }
+
+  private GroupDto updateName(DbSession dbSession, GroupDto group, @Nullable String newName) {
+    if (newName != null && !newName.equals(group.getName())) {
+      try {
+        UserGroupValidation.validateGroupName(newName);
+      } catch (IllegalArgumentException e) {
+        BadRequestException.throwBadRequestException(e.getMessage());
+      }
+      checkNameDoesNotExist(dbSession, newName);
+      group.setName(newName);
+      return dbClient.groupDao().update(dbSession, group);
+    }
+    return group;
+  }
+
+  private GroupDto updateDescription(DbSession dbSession, GroupDto group, @Nullable String newDescription) {
+    if (newDescription != null) {
+      group.setDescription(newDescription);
+      return dbClient.groupDao().update(dbSession, group);
+    }
+    return group;
+  }
+
   void checkNameDoesNotExist(DbSession dbSession, String name) {
     // There is no database constraint on column groups.name
     // because MySQL cannot create a unique index
index 4ecba2eca7f3c1ceaffc801a98570d84b6f08ee4..7220c4db33ff62a6061ae55c7a21c040a1a3c062 100644 (file)
@@ -24,7 +24,6 @@ import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.api.server.ws.WebService.NewController;
-import org.sonar.api.user.UserGroupValidation;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.user.GroupDto;
@@ -96,32 +95,16 @@ public class UpdateAction implements UserGroupsWsAction {
       String currentName = request.mandatoryParam(PARAM_GROUP_CURRENT_NAME);
 
       GroupDto group = dbClient.groupDao().selectByName(dbSession, currentName)
-          .orElseThrow(() -> new NotFoundException(format("Could not find a user group with name '%s'.", currentName)));
+        .orElseThrow(() -> new NotFoundException(format("Could not find a user group with name '%s'.", currentName)));
 
       userSession.checkPermission(ADMINISTER);
-      support.checkGroupIsNotDefault(dbSession, group);
-
-      boolean changed = false;
       String newName = request.param(PARAM_GROUP_NAME);
-      if (newName != null) {
-        changed = true;
-        UserGroupValidation.validateGroupName(newName);
-        support.checkNameDoesNotExist(dbSession, newName);
-        group.setName(newName);
-      }
-
       String description = request.param(PARAM_GROUP_DESCRIPTION);
-      if (description != null) {
-        changed = true;
-        group.setDescription(description);
-      }
 
-      if (changed) {
-        dbClient.groupDao().update(dbSession, group);
-        dbSession.commit();
-      }
+      GroupDto updatedGroup = support.updateGroup(dbSession, group, newName, description);
+      dbSession.commit();
 
-      writeResponse(dbSession, request, response, group);
+      writeResponse(dbSession, request, response, updatedGroup);
     }
   }
 
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/usergroups/ws/GroupWsSupportTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/usergroups/ws/GroupWsSupportTest.java
new file mode 100644 (file)
index 0000000..9a65795
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.usergroups.ws;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.usergroups.DefaultGroupFinder;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+
+@RunWith(DataProviderRunner.class)
+public class GroupWsSupportTest {
+
+  @Rule
+  public DbTester db = DbTester.create(System2.INSTANCE);
+
+  private final GroupWsSupport groupWsSupport = new GroupWsSupport(db.getDbClient(), new DefaultGroupFinder(db.getDbClient()));
+
+  @Test
+  public void updateGroup_updatesGroupNameAndDescription() {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    groupWsSupport.updateGroup(db.getSession(), group, "new-name", "New Description");
+    GroupDto updatedGroup = db.getDbClient().groupDao().selectByUuid(db.getSession(), group.getUuid());
+    assertThat(updatedGroup.getName()).isEqualTo("new-name");
+    assertThat(updatedGroup.getDescription()).isEqualTo("New Description");
+  }
+
+  public void updateGroup_updatesGroupName() {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    groupWsSupport.updateGroup(db.getSession(), group, "new-name");
+    GroupDto updatedGroup = db.getDbClient().groupDao().selectByUuid(db.getSession(), group.getUuid());
+    assertThat(updatedGroup.getName()).isEqualTo("new-name");
+  }
+
+  @Test
+  public void updateGroup_whenGroupIsDefault_throws() {
+    GroupDto defaultGroup = db.users().insertDefaultGroup();
+    DbSession session = db.getSession();
+    assertThatExceptionOfType(IllegalArgumentException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, defaultGroup, "new-name", "New Description"))
+      .withMessage("Default group 'sonar-users' cannot be used to perform this action");
+
+    assertThatExceptionOfType(IllegalArgumentException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, defaultGroup, "new-name"))
+      .withMessage("Default group 'sonar-users' cannot be used to perform this action");
+  }
+
+  @Test
+  public void updateGroup_whenGroupNameDoesntChange_succeedsWithDescription() {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    groupWsSupport.updateGroup(db.getSession(), group, group.getName(), "New Description");
+    GroupDto updatedGroup = db.getDbClient().groupDao().selectByUuid(db.getSession(), group.getUuid());
+    assertThat(updatedGroup.getDescription()).isEqualTo("New Description");
+  }
+
+  public void updateGroup_whenGroupNameDoesntChange_succeeds() {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    assertThatNoException()
+      .isThrownBy(() -> groupWsSupport.updateGroup(db.getSession(), group, group.getName()));
+  }
+
+  @Test
+  public void updateGroup_whenGroupExist_throws() {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    GroupDto group2 = db.users().insertGroup();
+    DbSession session = db.getSession();
+    String group2Name = group2.getName();
+
+    assertThatExceptionOfType(BadRequestException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, group, group2Name, "New Description"))
+      .withMessage("Group '" + group2Name + "' already exists");
+
+    assertThatExceptionOfType(BadRequestException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, group, group2Name))
+      .withMessage("Group '" + group2Name + "' already exists");
+  }
+
+  @Test
+  @UseDataProvider("invalidGroupNames")
+  public void updateGroup_whenGroupNameIsInvalid_throws(String groupName, String errorMessage) {
+    db.users().insertDefaultGroup();
+    GroupDto group = db.users().insertGroup();
+    DbSession session = db.getSession();
+
+    assertThatExceptionOfType(BadRequestException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, group, groupName, "New Description"))
+      .withMessage(errorMessage);
+
+    assertThatExceptionOfType(BadRequestException.class)
+      .isThrownBy(() -> groupWsSupport.updateGroup(session, group, groupName))
+      .withMessage(errorMessage);
+  }
+
+  @DataProvider
+  public static Object[][] invalidGroupNames() {
+    return new Object[][] {
+      {"", "Group name cannot be empty"},
+      {randomAlphanumeric(256), "Group name cannot be longer than 255 characters"},
+      {"Anyone", "Anyone group cannot be used"},
+    };
+  }
+
+}