]> source.dussan.org Git - sonarqube.git/blob
b61267214b2062963c2993dfa0b31b6ee52c843c
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.common.group.service;
21
22 import com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import java.util.stream.Collectors;
29 import org.junit.Before;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.mockito.ArgumentCaptor;
34 import org.mockito.Captor;
35 import org.mockito.InjectMocks;
36 import org.mockito.Mock;
37 import org.mockito.junit.MockitoJUnit;
38 import org.mockito.junit.MockitoRule;
39 import org.sonar.api.security.DefaultGroups;
40 import org.sonar.core.util.UuidFactory;
41 import org.sonar.db.DbClient;
42 import org.sonar.db.DbSession;
43 import org.sonar.db.permission.AuthorizationDao;
44 import org.sonar.db.permission.GlobalPermission;
45 import org.sonar.db.permission.template.PermissionTemplateDao;
46 import org.sonar.db.provisioning.GithubOrganizationGroupDao;
47 import org.sonar.db.qualitygate.QualityGateGroupPermissionsDao;
48 import org.sonar.db.qualityprofile.QProfileEditGroupsDao;
49 import org.sonar.db.scim.ScimGroupDao;
50 import org.sonar.db.user.ExternalGroupDao;
51 import org.sonar.db.user.GroupDao;
52 import org.sonar.db.user.GroupDto;
53 import org.sonar.db.user.GroupQuery;
54 import org.sonar.db.user.RoleDao;
55 import org.sonar.db.user.UserGroupDao;
56 import org.sonar.server.common.SearchResults;
57 import org.sonar.server.exceptions.BadRequestException;
58 import org.sonar.server.management.ManagedInstanceService;
59 import org.sonar.server.usergroups.DefaultGroupFinder;
60
61 import static java.lang.String.format;
62 import static java.util.function.Function.identity;
63 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
64 import static org.assertj.core.api.Assertions.assertThat;
65 import static org.assertj.core.api.Assertions.assertThatNoException;
66 import static org.assertj.core.api.Assertions.assertThatThrownBy;
67 import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
68 import static org.mockito.ArgumentMatchers.any;
69 import static org.mockito.ArgumentMatchers.anyInt;
70 import static org.mockito.ArgumentMatchers.eq;
71 import static org.mockito.Mockito.mock;
72 import static org.mockito.Mockito.never;
73 import static org.mockito.Mockito.verify;
74 import static org.mockito.Mockito.when;
75
76 @RunWith(DataProviderRunner.class)
77 public class GroupServiceTest {
78
79   private static final String GROUP_NAME = "GROUP_NAME";
80   private static final String GROUP_UUID = "GROUP_UUID";
81   private static final String DEFAULT_GROUP_NAME = "sonar-users";
82   private static final String DEFAULT_GROUP_UUID = "DEFAULT_GROUP_UUID";
83   @Mock
84   private DbSession dbSession;
85   @Mock
86   private DbClient dbClient;
87   @Mock
88   private UuidFactory uuidFactory;
89   @Mock
90   private DefaultGroupFinder defaultGroupFinder;
91   @Mock
92   private ManagedInstanceService managedInstanceService;
93   @InjectMocks
94   private GroupService groupService;
95
96   @Captor
97   private ArgumentCaptor<GroupQuery> queryCaptor;
98
99   @Rule
100   public MockitoRule rule = MockitoJUnit.rule();
101
102   @Before
103   public void setUp() {
104     mockNeededDaos();
105   }
106
107   private void mockNeededDaos() {
108     when(dbClient.authorizationDao()).thenReturn(mock(AuthorizationDao.class));
109     when(dbClient.roleDao()).thenReturn(mock(RoleDao.class));
110     when(dbClient.permissionTemplateDao()).thenReturn(mock(PermissionTemplateDao.class));
111     when(dbClient.userGroupDao()).thenReturn(mock(UserGroupDao.class));
112     when(dbClient.qProfileEditGroupsDao()).thenReturn(mock(QProfileEditGroupsDao.class));
113     when(dbClient.qualityGateGroupPermissionsDao()).thenReturn(mock(QualityGateGroupPermissionsDao.class));
114     when(dbClient.scimGroupDao()).thenReturn(mock(ScimGroupDao.class));
115     when(dbClient.externalGroupDao()).thenReturn(mock(ExternalGroupDao.class));
116     when(dbClient.groupDao()).thenReturn(mock(GroupDao.class));
117     when(dbClient.githubOrganizationGroupDao()).thenReturn(mock(GithubOrganizationGroupDao.class));
118   }
119
120   @Test
121   public void findGroup_whenGroupExists_returnsIt() {
122     GroupDto groupDto = mockGroupDto();
123
124     when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME))
125       .thenReturn(Optional.of(groupDto));
126
127     assertThat(groupService.findGroup(dbSession, GROUP_NAME)).contains(groupDto);
128   }
129
130   @Test
131   public void findGroup_whenGroupDoesntExist_returnsEmtpyOptional() {
132     when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME))
133       .thenReturn(Optional.empty());
134
135     assertThat(groupService.findGroup(dbSession, GROUP_NAME)).isEmpty();
136   }
137
138   @Test
139   public void findGroupByUuid_whenGroupExistsAndIsManagedAndDefault_returnsItWithCorrectValues() {
140     GroupDto groupDto = mockGroupDto();
141
142     when(defaultGroupFinder.findDefaultGroup(dbSession)).thenReturn(new GroupDto().setUuid(GROUP_UUID).setName("default-group"));
143
144     when(dbClient.groupDao().selectByUuid(dbSession, GROUP_UUID))
145       .thenReturn(groupDto);
146     when(managedInstanceService.isGroupManaged(dbSession, groupDto.getUuid())).thenReturn(true);
147
148     GroupInformation expected = new GroupInformation(groupDto, true, true);
149     assertThat(groupService.findGroupByUuid(dbSession, GROUP_UUID)).contains(expected);
150   }
151
152   @Test
153   public void findGroupByUuid_whenGroupExistsAndIsNotManagedAndDefault_returnsItWithCorrectValues() {
154     GroupDto groupDto = mockGroupDto();
155
156     when(defaultGroupFinder.findDefaultGroup(dbSession)).thenReturn(new GroupDto().setUuid("another-uuid").setName("default-group"));
157
158     when(dbClient.groupDao().selectByUuid(dbSession, GROUP_UUID))
159       .thenReturn(groupDto);
160     when(managedInstanceService.isGroupManaged(dbSession, groupDto.getUuid())).thenReturn(false);
161
162     GroupInformation expected = new GroupInformation(groupDto, false, false);
163     assertThat(groupService.findGroupByUuid(dbSession, GROUP_UUID)).contains(expected);
164   }
165
166   @Test
167   public void findGroupByUuid_whenGroupDoesntExist_returnsEmptyOptional() {
168     when(dbClient.groupDao().selectByUuid(dbSession, GROUP_UUID))
169       .thenReturn(null);
170
171     assertThat(groupService.findGroupByUuid(dbSession, GROUP_UUID)).isEmpty();
172   }
173
174   @Test
175   public void delete_whenNotDefaultAndNotLastAdminGroup_deleteGroup() {
176     GroupDto groupDto = mockGroupDto();
177
178     when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
179       .thenReturn(Optional.of(new GroupDto().setUuid("another_group_uuid")));
180     when(dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingGroup(dbSession, GlobalPermission.ADMINISTER.getKey(), groupDto.getUuid()))
181       .thenReturn(2);
182
183     groupService.delete(dbSession, groupDto);
184
185     verifyGroupDelete(dbSession, groupDto);
186   }
187
188   @Test
189   public void delete_whenDefaultGroup_throwAndDontDeleteGroup() {
190     GroupDto groupDto = mockGroupDto();
191
192     when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
193       .thenReturn(Optional.of(groupDto));
194
195     assertThatThrownBy(() -> groupService.delete(dbSession, groupDto))
196       .isInstanceOf(IllegalArgumentException.class)
197       .hasMessage(format("Default group '%s' cannot be used to perform this action", GROUP_NAME));
198
199     verifyNoGroupDelete(dbSession, groupDto);
200   }
201
202   @Test
203   public void delete_whenLastAdminGroup_throwAndDontDeleteGroup() {
204     GroupDto groupDto = mockGroupDto();
205
206     when(dbClient.groupDao().selectByName(dbSession, DefaultGroups.USERS))
207       .thenReturn(Optional.of(new GroupDto().setUuid("another_group_uuid"))); // We must pass the default group check
208     when(dbClient.authorizationDao().countUsersWithGlobalPermissionExcludingGroup(dbSession, GlobalPermission.ADMINISTER.getKey(), groupDto.getUuid()))
209       .thenReturn(0);
210
211     assertThatThrownBy(() -> groupService.delete(dbSession, groupDto))
212       .isInstanceOf(IllegalArgumentException.class)
213       .hasMessage("The last system admin group cannot be deleted");
214
215     verifyNoGroupDelete(dbSession, groupDto);
216   }
217
218   @Test
219   public void updateGroup_updatesGroupNameAndDescription() {
220     GroupDto group = mockGroupDto();
221     GroupDto groupWithUpdatedName = mockGroupDto();
222     GroupDto groupWithUpdatedDescription = mockGroupDto();
223     mockDefaultGroup();
224     when(dbClient.groupDao().update(dbSession, group)).thenReturn(groupWithUpdatedName);
225     when(dbClient.groupDao().update(dbSession, groupWithUpdatedName)).thenReturn(groupWithUpdatedDescription);
226
227     groupService.updateGroup(dbSession, group, "new-name", "New Description");
228     verify(group).setName("new-name");
229     verify(groupWithUpdatedName).setDescription("New Description");
230     verify(dbClient.groupDao()).update(dbSession, group);
231     verify(dbClient.groupDao()).update(dbSession, groupWithUpdatedName);
232   }
233
234   @Test
235   public void updateGroup_updatesGroupName() {
236     GroupDto group = mockGroupDto();
237     mockDefaultGroup();
238
239     when(dbClient.groupDao().update(dbSession, group)).thenReturn(group);
240     groupService.updateGroup(dbSession, group, "new-name");
241     verify(group).setName("new-name");
242     verify(dbClient.groupDao()).update(dbSession, group);
243   }
244
245   @Test
246   public void updateGroup_whenGroupIsDefault_throws() {
247     GroupDto defaultGroup = mockDefaultGroup();
248     when(dbClient.groupDao().selectByName(dbSession, DEFAULT_GROUP_NAME)).thenReturn(Optional.of(defaultGroup));
249
250     assertThatExceptionOfType(IllegalArgumentException.class)
251       .isThrownBy(() -> groupService.updateGroup(dbSession, defaultGroup, "new-name", "New Description"))
252       .withMessage("Default group 'sonar-users' cannot be used to perform this action");
253
254     assertThatExceptionOfType(IllegalArgumentException.class)
255       .isThrownBy(() -> groupService.updateGroup(dbSession, defaultGroup, "new-name"))
256       .withMessage("Default group 'sonar-users' cannot be used to perform this action");
257   }
258
259   @Test
260   public void updateGroup_whenGroupNameDoesntChange_succeedsWithDescription() {
261     GroupDto group = mockGroupDto();
262     mockDefaultGroup();
263
264     when(dbClient.groupDao().update(dbSession, group)).thenReturn(group);
265     groupService.updateGroup(dbSession, group, group.getName(), "New Description");
266
267     verify(group).setDescription("New Description");
268     verify(dbClient.groupDao()).update(dbSession, group);
269   }
270
271   @Test
272   public void updateGroup_whenGroupNameDoesntChange_succeeds() {
273     GroupDto group = mockGroupDto();
274     mockDefaultGroup();
275
276     assertThatNoException()
277       .isThrownBy(() -> groupService.updateGroup(dbSession, group, group.getName()));
278
279     verify(dbClient.groupDao(), never()).update(dbSession, group);
280   }
281
282   @Test
283   public void updateGroup_whenGroupExist_throws() {
284     GroupDto group = mockGroupDto();
285     GroupDto group2 = mockGroupDto();
286     mockDefaultGroup();
287     String group2Name = GROUP_NAME + "2";
288
289     when(dbClient.groupDao().selectByName(dbSession, group2Name)).thenReturn(Optional.of(group2));
290
291     assertThatExceptionOfType(BadRequestException.class)
292       .isThrownBy(() -> groupService.updateGroup(dbSession, group, group2Name, "New Description"))
293       .withMessage("Group '" + group2Name + "' already exists");
294
295     assertThatExceptionOfType(BadRequestException.class)
296       .isThrownBy(() -> groupService.updateGroup(dbSession, group, group2Name))
297       .withMessage("Group '" + group2Name + "' already exists");
298   }
299
300   @Test
301   @UseDataProvider("invalidGroupNames")
302   public void updateGroup_whenGroupNameIsInvalid_throws(String groupName, String errorMessage) {
303     GroupDto group = mockGroupDto();
304     mockDefaultGroup();
305
306     assertThatExceptionOfType(BadRequestException.class)
307       .isThrownBy(() -> groupService.updateGroup(dbSession, group, groupName, "New Description"))
308       .withMessage(errorMessage);
309
310     assertThatExceptionOfType(BadRequestException.class)
311       .isThrownBy(() -> groupService.updateGroup(dbSession, group, groupName))
312       .withMessage(errorMessage);
313   }
314
315   @Test
316   public void createGroup_whenNameAndDescriptionIsProvided_createsGroup() {
317
318     when(uuidFactory.create()).thenReturn("1234");
319     GroupDto createdGroup  = mockGroupDto();
320     when(dbClient.groupDao().insert(eq(dbSession), any())).thenReturn(createdGroup);
321     mockDefaultGroup();
322     groupService.createGroup(dbSession, "Name", "Description");
323
324     ArgumentCaptor<GroupDto> groupCaptor = ArgumentCaptor.forClass(GroupDto.class);
325     verify(dbClient.groupDao()).insert(eq(dbSession), groupCaptor.capture());
326     GroupDto groupToCreate = groupCaptor.getValue();
327     assertThat(groupToCreate.getName()).isEqualTo("Name");
328     assertThat(groupToCreate.getDescription()).isEqualTo("Description");
329     assertThat(groupToCreate.getUuid()).isEqualTo("1234");
330   }
331
332   @Test
333   public void createGroup_whenGroupExist_throws() {
334     GroupDto group = mockGroupDto();
335
336     when(dbClient.groupDao().selectByName(dbSession, GROUP_NAME)).thenReturn(Optional.of(group));
337
338     assertThatExceptionOfType(BadRequestException.class)
339       .isThrownBy(() -> groupService.createGroup(dbSession, GROUP_NAME, "New Description"))
340       .withMessage("Group '" + GROUP_NAME + "' already exists");
341
342   }
343
344   @Test
345   @UseDataProvider("invalidGroupNames")
346   public void createGroup_whenGroupNameIsInvalid_throws(String groupName, String errorMessage) {
347     mockDefaultGroup();
348
349     assertThatExceptionOfType(BadRequestException.class)
350       .isThrownBy(() -> groupService.createGroup(dbSession, groupName, "Description"))
351       .withMessage(errorMessage);
352
353   }
354
355   @DataProvider
356   public static Object[][] invalidGroupNames() {
357     return new Object[][] {
358       {"", "Group name cannot be empty"},
359       {randomAlphanumeric(256), "Group name cannot be longer than 255 characters"},
360       {"Anyone", "Anyone group cannot be used"},
361     };
362   }
363
364   @Test
365   public void search_whenSeveralGroupFound_returnsThem() {
366     GroupDto groupDto1 = mockGroupDto("1");
367     GroupDto groupDto2 = mockGroupDto("2");
368     GroupDto defaultGroup = mockDefaultGroup();
369
370     when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), eq(5), eq(24)))
371       .thenReturn(List.of(groupDto1, groupDto2, defaultGroup));
372
373     Map<String, Boolean> groupUuidToManaged = Map.of(
374       groupDto1.getUuid(), false,
375       groupDto2.getUuid(), true,
376       defaultGroup.getUuid(), false);
377     when(managedInstanceService.getGroupUuidToManaged(dbSession, groupUuidToManaged.keySet())).thenReturn(groupUuidToManaged);
378
379     when(dbClient.groupDao().countByQuery(eq(dbSession), any())).thenReturn(300);
380
381     SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, 5, 24));
382     assertThat(searchResults.total()).isEqualTo(300);
383
384     Map<String, GroupInformation> uuidToGroupInformation = searchResults.searchResults().stream()
385       .collect(Collectors.toMap(groupInformation -> groupInformation.groupDto().getUuid(), identity()));
386     assertGroupInformation(uuidToGroupInformation, groupDto1, false, false);
387     assertGroupInformation(uuidToGroupInformation, groupDto2, true, false);
388     assertGroupInformation(uuidToGroupInformation, defaultGroup, false, true);
389
390     assertThat(queryCaptor.getValue().getSearchText()).isEqualTo("%QUERY%");
391     assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isNull();
392   }
393   @Test
394   public void search_whenPageSizeEquals0_returnsOnlyTotal() {
395     when(dbClient.groupDao().countByQuery(eq(dbSession), any())).thenReturn(10);
396
397     SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, 0, 24));
398     assertThat(searchResults.total()).isEqualTo(10);
399     assertThat(searchResults.searchResults()).isEmpty();
400
401     verify(dbClient.groupDao(), never()).selectByQuery(eq(dbSession), any(), anyInt(), anyInt());
402   }
403
404   @Test
405   public void search_whenInstanceManagedAndManagedIsTrue_addsManagedClause() {
406     mockManagedInstance();
407     when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
408
409     groupService.search(dbSession, new GroupSearchRequest("query", true, 5, 24));
410
411     assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isEqualTo("managed_filter");
412   }
413
414   @Test
415   public void search_whenInstanceManagedAndManagedIsFalse_addsManagedClause() {
416     mockManagedInstance();
417     when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
418
419     groupService.search(dbSession, new GroupSearchRequest("query", false, 5, 24));
420
421     assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isEqualTo("not_managed_filter");
422   }
423
424   @Test
425   public void search_whenInstanceNotManagedAndManagedIsTrue_throws() {
426     assertThatExceptionOfType(BadRequestException.class)
427       .isThrownBy(() -> groupService.search(dbSession, new GroupSearchRequest("query", true, 5, 24)))
428       .withMessage("The 'managed' parameter is only available for managed instances.");
429   }
430
431   private void mockManagedInstance() {
432     when(managedInstanceService.isInstanceExternallyManaged()).thenReturn(true);
433     when(managedInstanceService.getManagedGroupsSqlFilter(true)).thenReturn("managed_filter");
434     when(managedInstanceService.getManagedGroupsSqlFilter(false)).thenReturn("not_managed_filter");
435   }
436
437   private static void assertGroupInformation(Map<String, GroupInformation> uuidToGroupInformation, GroupDto expectedGroupDto, boolean expectedManaged, boolean expectedDefault) {
438     assertThat(uuidToGroupInformation.get(expectedGroupDto.getUuid()).groupDto()).isEqualTo(expectedGroupDto);
439     assertThat(uuidToGroupInformation.get(expectedGroupDto.getUuid()).isManaged()).isEqualTo(expectedManaged);
440     assertThat(uuidToGroupInformation.get(expectedGroupDto.getUuid()).isDefault()).isEqualTo(expectedDefault);
441   }
442
443   private static GroupDto mockGroupDto() {
444     GroupDto groupDto = mock(GroupDto.class);
445     when(groupDto.getName()).thenReturn(GROUP_NAME);
446     when(groupDto.getUuid()).thenReturn(GROUP_UUID);
447     return groupDto;
448   }
449
450   private static GroupDto mockGroupDto(String id) {
451     GroupDto groupDto = mock(GroupDto.class);
452     when(groupDto.getUuid()).thenReturn(id);
453     when(groupDto.getName()).thenReturn("name_" + id);
454     return groupDto;
455   }
456
457   private GroupDto mockDefaultGroup() {
458     GroupDto defaultGroup = mock(GroupDto.class);
459     when(defaultGroup.getName()).thenReturn(DEFAULT_GROUP_NAME);
460     when(defaultGroup.getUuid()).thenReturn(DEFAULT_GROUP_UUID);
461     when(dbClient.groupDao().selectByName(dbSession, DEFAULT_GROUP_NAME)).thenReturn(Optional.of(defaultGroup));
462     when(defaultGroupFinder.findDefaultGroup(dbSession)).thenReturn(defaultGroup);
463     return defaultGroup;
464   }
465
466   private void verifyNoGroupDelete(DbSession dbSession, GroupDto groupDto) {
467     verify(dbClient.roleDao(), never()).deleteGroupRolesByGroupUuid(dbSession, groupDto.getUuid());
468     verify(dbClient.permissionTemplateDao(), never()).deleteByGroup(dbSession, groupDto.getUuid(), groupDto.getName());
469     verify(dbClient.userGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid(), groupDto.getName());
470     verify(dbClient.qProfileEditGroupsDao(), never()).deleteByGroup(dbSession, groupDto);
471     verify(dbClient.qualityGateGroupPermissionsDao(), never()).deleteByGroup(dbSession, groupDto);
472     verify(dbClient.scimGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid());
473     verify(dbClient.groupDao(), never()).deleteByUuid(dbSession, groupDto.getUuid(), groupDto.getName());
474     verify(dbClient.githubOrganizationGroupDao(), never()).deleteByGroupUuid(dbSession, groupDto.getUuid());
475   }
476
477   private void verifyGroupDelete(DbSession dbSession, GroupDto groupDto) {
478     verify(dbClient.roleDao()).deleteGroupRolesByGroupUuid(dbSession, groupDto.getUuid());
479     verify(dbClient.permissionTemplateDao()).deleteByGroup(dbSession, groupDto.getUuid(), groupDto.getName());
480     verify(dbClient.userGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid(), groupDto.getName());
481     verify(dbClient.qProfileEditGroupsDao()).deleteByGroup(dbSession, groupDto);
482     verify(dbClient.qualityGateGroupPermissionsDao()).deleteByGroup(dbSession, groupDto);
483     verify(dbClient.scimGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
484     verify(dbClient.externalGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
485     verify(dbClient.groupDao()).deleteByUuid(dbSession, groupDto.getUuid(), groupDto.getName());
486     verify(dbClient.githubOrganizationGroupDao()).deleteByGroupUuid(dbSession, groupDto.getUuid());
487   }
488 }