aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-common
diff options
context:
space:
mode:
authorWojtek Wajerowicz <115081248+wojciech-wajerowicz-sonarsource@users.noreply.github.com>2023-11-21 11:59:19 +0100
committersonartech <sonartech@sonarsource.com>2023-11-23 20:02:57 +0000
commit6918599a8059b3c561ada4f26817b559c12e687e (patch)
tree47e0d9133b38392a7ec63080ee28ae6872edf874 /server/sonar-webserver-common
parent7e76009e29913a70911aab85031ed79759c2d45a (diff)
downloadsonarqube-6918599a8059b3c561ada4f26817b559c12e687e.tar.gz
sonarqube-6918599a8059b3c561ada4f26817b559c12e687e.zip
SONAR-21058 API v2 GET /authorizations/groups/{groupId}
Diffstat (limited to 'server/sonar-webserver-common')
-rw-r--r--server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java179
-rw-r--r--server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/package-info.java23
-rw-r--r--server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java357
3 files changed, 559 insertions, 0 deletions
diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java
new file mode 100644
index 00000000000..4e28d96fcfd
--- /dev/null
+++ b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java
@@ -0,0 +1,179 @@
+/*
+ * 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.common.group.service;
+
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.user.UserGroupValidation;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.exceptions.BadRequestException;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.server.exceptions.BadRequestException.checkRequest;
+
+@ServerSide
+public class GroupService {
+
+ private final DbClient dbClient;
+ private final UuidFactory uuidFactory;
+
+ public GroupService(DbClient dbClient, UuidFactory uuidFactory) {
+ this.dbClient = dbClient;
+ this.uuidFactory = uuidFactory;
+ }
+
+ public Optional<GroupDto> findGroup(DbSession dbSession, String groupName) {
+ return dbClient.groupDao().selectByName(dbSession, groupName);
+ }
+
+ public Optional<GroupDto> findGroupByUuid(DbSession dbSession, String groupUuid) {
+ return Optional.ofNullable(dbClient.groupDao().selectByUuid(dbSession, groupUuid));
+ }
+
+ public void delete(DbSession dbSession, GroupDto group) {
+ checkGroupIsNotDefault(dbSession, group);
+ checkNotTryingToDeleteLastAdminGroup(dbSession, group);
+
+ removeGroupPermissions(dbSession, group);
+ removeGroupFromPermissionTemplates(dbSession, group);
+ removeGroupMembers(dbSession, group);
+ removeGroupFromQualityProfileEdit(dbSession, group);
+ removeGroupFromQualityGateEdit(dbSession, group);
+ removeGroupScimLink(dbSession, group);
+ removeExternalGroupMapping(dbSession, group);
+ removeGithubOrganizationGroup(dbSession, group);
+
+ removeGroup(dbSession, group);
+ }
+
+ 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);
+ }
+
+ public GroupDto createGroup(DbSession dbSession, String name, @Nullable String description) {
+ validateGroupName(name);
+ checkNameDoesNotExist(dbSession, name);
+
+ GroupDto group = new GroupDto()
+ .setUuid(uuidFactory.create())
+ .setName(name)
+ .setDescription(description);
+ return dbClient.groupDao().insert(dbSession, group);
+ }
+
+ private GroupDto updateName(DbSession dbSession, GroupDto group, @Nullable String newName) {
+ if (newName != null && !newName.equals(group.getName())) {
+ validateGroupName(newName);
+ checkNameDoesNotExist(dbSession, newName);
+ group.setName(newName);
+ return dbClient.groupDao().update(dbSession, group);
+ }
+ return group;
+ }
+
+ private static void validateGroupName(String name) {
+ try {
+ UserGroupValidation.validateGroupName(name);
+ } catch (IllegalArgumentException e) {
+ BadRequestException.throwBadRequestException(e.getMessage());
+ }
+ }
+
+ private void checkNameDoesNotExist(DbSession dbSession, String name) {
+ // There is no database constraint on column groups.name
+ // because MySQL cannot create a unique index
+ // on a UTF-8 VARCHAR larger than 255 characters on InnoDB
+ checkRequest(!dbClient.groupDao().selectByName(dbSession, name).isPresent(), "Group '%s' already exists", name);
+ }
+
+ private GroupDto updateDescription(DbSession dbSession, GroupDto group, @Nullable String newDescription) {
+ if (newDescription != null) {
+ group.setDescription(newDescription);
+ return dbClient.groupDao().update(dbSession, group);
+ }
+ return group;
+ }
+
+ private void checkGroupIsNotDefault(DbSession dbSession, GroupDto groupDto) {
+ GroupDto defaultGroup = findDefaultGroup(dbSession);
+ checkArgument(!defaultGroup.getUuid().equals(groupDto.getUuid()), "Default group '%s' cannot be used to perform this action", groupDto.getName());
+ }
+
+ private GroupDto findDefaultGroup(DbSession dbSession) {
+ return dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS)
+ .orElseThrow(() -> new IllegalStateException("Default group cannot be found"));
+ }
+
+ private void checkNotTryingToDeleteLastAdminGroup(DbSession dbSession, GroupDto group) {
+ int remaining = dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingGroup(dbSession,
+ GlobalPermission.ADMINISTER.getKey(), group.getUuid());
+
+ checkArgument(remaining > 0, "The last system admin group cannot be deleted");
+ }
+
+ private void removeGroupPermissions(DbSession dbSession, GroupDto group) {
+ dbClient.roleDao().deleteGroupRolesByGroupUuid(dbSession, group.getUuid());
+ }
+
+ private void removeGroupFromPermissionTemplates(DbSession dbSession, GroupDto group) {
+ dbClient.permissionTemplateDao().deleteByGroup(dbSession, group.getUuid(), group.getName());
+ }
+
+ private void removeGroupMembers(DbSession dbSession, GroupDto group) {
+ dbClient.userGroupDao().deleteByGroupUuid(dbSession, group.getUuid(), group.getName());
+ }
+
+ private void removeGroupFromQualityProfileEdit(DbSession dbSession, GroupDto group) {
+ dbClient.qProfileEditGroupsDao().deleteByGroup(dbSession, group);
+ }
+
+ private void removeGroupFromQualityGateEdit(DbSession dbSession, GroupDto group) {
+ dbClient.qualityGateGroupPermissionsDao().deleteByGroup(dbSession, group);
+ }
+
+ private void removeGroupScimLink(DbSession dbSession, GroupDto group) {
+ dbClient.scimGroupDao().deleteByGroupUuid(dbSession, group.getUuid());
+ }
+
+ private void removeExternalGroupMapping(DbSession dbSession, GroupDto group) {
+ dbClient.externalGroupDao().deleteByGroupUuid(dbSession, group.getUuid());
+ }
+ private void removeGithubOrganizationGroup(DbSession dbSession, GroupDto group) {
+ dbClient.githubOrganizationGroupDao().deleteByGroupUuid(dbSession, group.getUuid());
+ }
+
+ private void removeGroup(DbSession dbSession, GroupDto group) {
+ dbClient.groupDao().deleteByUuid(dbSession, group.getUuid(), group.getName());
+ }
+
+}
diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/package-info.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/package-info.java
new file mode 100644
index 00000000000..3e126243ab7
--- /dev/null
+++ b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.server.common.group.service;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java
new file mode 100644
index 00000000000..f64f4e1c200
--- /dev/null
+++ b/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.common.group.service;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.permission.AuthorizationDao;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.permission.template.PermissionTemplateDao;
+import org.sonar.db.provisioning.GithubOrganizationGroupDao;
+import org.sonar.db.qualitygate.QualityGateGroupPermissionsDao;
+import org.sonar.db.qualityprofile.QProfileEditGroupsDao;
+import org.sonar.db.scim.ScimGroupDao;
+import org.sonar.db.user.ExternalGroupDao;
+import org.sonar.db.user.GroupDao;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.RoleDao;
+import org.sonar.db.user.UserGroupDao;
+import org.sonar.server.exceptions.BadRequestException;
+
+import static java.lang.String.format;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(DataProviderRunner.class)
+public class GroupServiceTest {
+
+ private static final String GROUP_NAME = "GROUP_NAME";
+ private static final String GROUP_UUID = "GROUP_UUID";
+ private static final String DEFAULT_GROUP_NAME = "sonar-users";
+ private static final String DEFAULT_GROUP_UUID = "DEFAULT_GROUP_UUID";
+ @Mock
+ private DbSession dbSession;
+ @Mock
+ private DbClient dbClient;
+ @Mock
+ private UuidFactory uuidFactory;
+ @InjectMocks
+ private GroupService groupService;
+
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
+
+ @Before
+ public void setUp() {
+ mockNeededDaos();
+ }
+
+ private void mockNeededDaos() {
+ when(dbClient.authorizationDao()).thenReturn(mock(AuthorizationDao.class));
+ when(dbClient.roleDao()).thenReturn(mock(RoleDao.class));
+ when(dbClient.permissionTemplateDao()).thenReturn(mock(PermissionTemplateDao.class));
+ when(dbClient.userGroupDao()).thenReturn(mock(UserGroupDao.class));
+ when(dbClient.qProfileEditGroupsDao()).thenReturn(mock(QProfileEditGroupsDao.class));
+ when(dbClient.qualityGateGroupPermissionsDao()).thenReturn(mock(QualityGateGroupPermissionsDao.class));
+ when(dbClient.scimGroupDao()).thenReturn(mock(ScimGroupDao.class));
+ when(dbClient.externalGroupDao()).thenReturn(mock(ExternalGroupDao.class));
+ when(dbClient.groupDao()).thenReturn(mock(GroupDao.class));
+ when(dbClient.githubOrganizationGroupDao()).thenReturn(mock(GithubOrganizationGroupDao.class));
+ }
+
+ @Test
+ public void findGroup_whenGroupExists_returnsIt() {
+ GroupDto groupDto = mockGroupDto();
+
+ when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME))
+ .thenReturn(Optional.of(groupDto));
+
+ assertThat(groupService.findGroup(dbSession, GROUP_NAME)).contains(groupDto);
+ }
+
+ @Test
+ public void findGroup_whenGroupDoesntExist_returnsEmtpyOptional() {
+ when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME))
+ .thenReturn(Optional.empty());
+
+ assertThat(groupService.findGroup(dbSession, GROUP_NAME)).isEmpty();
+ }
+
+ @Test
+ public void findGroupByUuid_whenGroupExists_returnsIt() {
+ GroupDto groupDto = mockGroupDto();
+
+ when(dbClient.groupDao().selectByUuid(dbSession, GROUP_UUID))
+ .thenReturn(groupDto);
+
+ assertThat(groupService.findGroupByUuid(dbSession, GROUP_UUID)).contains(groupDto);
+ }
+
+ @Test
+ public void findGroupByUuid_whenGroupDoesntExist_returnsEmptyOptional() {
+ when(dbClient.groupDao().selectByUuid(dbSession, GROUP_UUID))
+ .thenReturn(null);
+
+ assertThat(groupService.findGroupByUuid(dbSession, GROUP_UUID)).isEmpty();
+ }
+
+ @Test
+ public void delete_whenNotDefaultAndNotLastAdminGroup_deleteGroup() {
+ GroupDto groupDto = mockGroupDto();
+
+ when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
+ .thenReturn(Optional.of(new GroupDto().setUuid("another_group_uuid")));
+ when(dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingGroup(dbSession, GlobalPermission.ADMINISTER.getKey(), groupDto.getUuid()))
+ .thenReturn(2);
+
+ groupService.delete(dbSession, groupDto);
+
+ verifyGroupDelete(dbSession, groupDto);
+ }
+
+ @Test
+ public void delete_whenDefaultGroup_throwAndDontDeleteGroup() {
+ GroupDto groupDto = mockGroupDto();
+
+ when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
+ .thenReturn(Optional.of(groupDto));
+
+ assertThatThrownBy(() -> groupService.delete(dbSession, groupDto))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage(format("Default group '%s' cannot be used to perform this action", GROUP_NAME));
+
+ verifyNoGroupDelete(dbSession, groupDto);
+ }
+
+ @Test
+ public void delete_whenLastAdminGroup_throwAndDontDeleteGroup() {
+ GroupDto groupDto = mockGroupDto();
+
+ when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
+ .thenReturn(Optional.of(new GroupDto().setUuid("another_group_uuid"))); // We must pass the default group check
+ when(dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingGroup(dbSession, GlobalPermission.ADMINISTER.getKey(), groupDto.getUuid()))
+ .thenReturn(0);
+
+ assertThatThrownBy(() -> groupService.delete(dbSession, groupDto))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("The last system admin group cannot be deleted");
+
+ verifyNoGroupDelete(dbSession, groupDto);
+ }
+
+ @Test
+ public void updateGroup_updatesGroupNameAndDescription() {
+ GroupDto group = mockGroupDto();
+ GroupDto groupWithUpdatedName = mockGroupDto();
+ mockDefaultGroup();
+ when(dbClient.groupDao().update(dbSession, group)).thenReturn(groupWithUpdatedName);
+
+ groupService.updateGroup(dbSession, group, "new-name", "New Description");
+ verify(group).setName("new-name");
+ verify(groupWithUpdatedName).setDescription("New Description");
+ verify(dbClient.groupDao()).update(dbSession, group);
+ verify(dbClient.groupDao()).update(dbSession, groupWithUpdatedName);
+ }
+
+ @Test
+ public void updateGroup_updatesGroupName() {
+ GroupDto group = mockGroupDto();
+ mockDefaultGroup();
+
+ groupService.updateGroup(dbSession, group, "new-name");
+ verify(group).setName("new-name");
+ verify(dbClient.groupDao()).update(dbSession, group);
+ }
+
+ @Test
+ public void updateGroup_whenGroupIsDefault_throws() {
+ GroupDto defaultGroup = mockDefaultGroup();
+ when(dbClient.groupDao().selectByName(dbSession, DEFAULT_GROUP_NAME)).thenReturn(Optional.of(defaultGroup));
+
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, defaultGroup, "new-name", "New Description"))
+ .withMessage("Default group 'sonar-users' cannot be used to perform this action");
+
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, defaultGroup, "new-name"))
+ .withMessage("Default group 'sonar-users' cannot be used to perform this action");
+ }
+
+ @Test
+ public void updateGroup_whenGroupNameDoesntChange_succeedsWithDescription() {
+ GroupDto group = mockGroupDto();
+ mockDefaultGroup();
+
+ groupService.updateGroup(dbSession, group, group.getName(), "New Description");
+ verify(group).setDescription("New Description");
+ verify(dbClient.groupDao()).update(dbSession, group);
+ }
+
+ @Test
+ public void updateGroup_whenGroupNameDoesntChange_succeeds() {
+ GroupDto group = mockGroupDto();
+ mockDefaultGroup();
+
+ assertThatNoException()
+ .isThrownBy(() -> groupService.updateGroup(dbSession, group, group.getName()));
+
+ verify(dbClient.groupDao(), never()).update(dbSession, group);
+ }
+
+ @Test
+ public void updateGroup_whenGroupExist_throws() {
+ GroupDto group = mockGroupDto();
+ GroupDto group2 = mockGroupDto();
+ mockDefaultGroup();
+ String group2Name = GROUP_NAME + "2";
+
+ when(dbClient.groupDao().selectByName(dbSession, group2Name)).thenReturn(Optional.of(group2));
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, group, group2Name, "New Description"))
+ .withMessage("Group '" + group2Name + "' already exists");
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, group, group2Name))
+ .withMessage("Group '" + group2Name + "' already exists");
+ }
+
+ @Test
+ @UseDataProvider("invalidGroupNames")
+ public void updateGroup_whenGroupNameIsInvalid_throws(String groupName, String errorMessage) {
+ GroupDto group = mockGroupDto();
+ mockDefaultGroup();
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, group, groupName, "New Description"))
+ .withMessage(errorMessage);
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.updateGroup(dbSession, group, groupName))
+ .withMessage(errorMessage);
+ }
+
+ @Test
+ public void createGroup_whenNameAndDescriptionIsProvided_createsGroup() {
+
+ when(uuidFactory.create()).thenReturn("1234");
+ groupService.createGroup(dbSession, "Name", "Description");
+
+ ArgumentCaptor<GroupDto> groupCaptor = ArgumentCaptor.forClass(GroupDto.class);
+ verify(dbClient.groupDao()).insert(eq(dbSession), groupCaptor.capture());
+ GroupDto createdGroup = groupCaptor.getValue();
+ assertThat(createdGroup.getName()).isEqualTo("Name");
+ assertThat(createdGroup.getDescription()).isEqualTo("Description");
+ assertThat(createdGroup.getUuid()).isEqualTo("1234");
+ }
+
+ @Test
+ public void createGroup_whenGroupExist_throws() {
+ GroupDto group = mockGroupDto();
+
+ when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME)).thenReturn(Optional.of(group));
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.createGroup(dbSession, GROUP_NAME, "New Description"))
+ .withMessage("Group '" + GROUP_NAME + "' already exists");
+
+ }
+
+ @Test
+ @UseDataProvider("invalidGroupNames")
+ public void createGroup_whenGroupNameIsInvalid_throws(String groupName, String errorMessage) {
+ mockDefaultGroup();
+
+ assertThatExceptionOfType(BadRequestException.class)
+ .isThrownBy(() -> groupService.createGroup(dbSession, groupName, "Description"))
+ .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"},
+ };
+ }
+
+ private static GroupDto mockGroupDto() {
+ GroupDto groupDto = mock(GroupDto.class);
+ when(groupDto.getName()).thenReturn(GROUP_NAME);
+ when(groupDto.getUuid()).thenReturn(GROUP_UUID);
+ return groupDto;
+ }
+
+ private GroupDto mockDefaultGroup() {
+ GroupDto defaultGroup = mock(GroupDto.class);
+ when(defaultGroup.getName()).thenReturn(DEFAULT_GROUP_NAME);
+ when(defaultGroup.getUuid()).thenReturn(DEFAULT_GROUP_UUID);
+ when(dbClient.groupDao().selectByName(dbSession, DEFAULT_GROUP_NAME)).thenReturn(Optional.of(defaultGroup));
+ return defaultGroup;
+ }
+
+ private void verifyNoGroupDelete(DbSession dbSession, GroupDto groupDto) {
+ verify(dbClient.roleDao(), never()).deleteGroupRolesByGroupUuid(dbSession, groupDto.getUuid());
+ verify(dbClient.permissionTemplateDao(), never()).deleteByGroup(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.userGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.qProfileEditGroupsDao(), never()).deleteByGroup(dbSession, groupDto);
+ verify(dbClient.qualityGateGroupPermissionsDao(), never()).deleteByGroup(dbSession, groupDto);
+ verify(dbClient.scimGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid());
+ verify(dbClient.groupDao(), never()).deleteByUuid(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.githubOrganizationGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid());
+ }
+
+ private void verifyGroupDelete(DbSession dbSession, GroupDto groupDto) {
+ verify(dbClient.roleDao()).deleteGroupRolesByGroupUuid(dbSession, groupDto.getUuid());
+ verify(dbClient.permissionTemplateDao()).deleteByGroup(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.userGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.qProfileEditGroupsDao()).deleteByGroup(dbSession, groupDto);
+ verify(dbClient.qualityGateGroupPermissionsDao()).deleteByGroup(dbSession, groupDto);
+ verify(dbClient.scimGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
+ verify(dbClient.externalGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
+ verify(dbClient.groupDao()).deleteByUuid(dbSession, groupDto.getUuid(), groupDto.getName());
+ verify(dbClient.githubOrganizationGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
+ }
+}