From c7dde86fd2ffb20ad365b1eda4ebcf7dd68ea494 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Tue, 19 Jun 2018 15:38:19 +0200 Subject: [PATCH] SONARCLOUD-61 automatically enable organizations on sonarcloud edition startup --- .../organization/OrganisationSupport.java | 121 ++++++++++ .../organization/ws/EnableSupportAction.java | 98 +------- .../ws/OrganizationsWsModule.java | 2 + .../organization/OrganisationSupportTest.java | 219 ++++++++++++++++++ .../ws/EnableSupportActionTest.java | 181 +-------------- .../ws/OrganizationsWsModuleTest.java | 2 +- 6 files changed, 359 insertions(+), 264 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java new file mode 100644 index 00000000000..6df90782bf7 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganisationSupport.java @@ -0,0 +1,121 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.organization; + +import java.util.List; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.server.ServerSide; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.permission.GroupPermissionDto; +import org.sonar.db.permission.template.PermissionTemplateGroupDto; +import org.sonar.db.rule.RuleDefinitionDto; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.UserGroupDto; +import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.usergroups.DefaultGroupCreator; +import org.sonar.server.usergroups.DefaultGroupFinder; + +import static org.sonar.core.util.stream.MoreCollectors.toList; + +@ServerSide +public class OrganisationSupport { + private final DbClient dbClient; + private final DefaultOrganizationProvider defaultOrganizationProvider; + private final OrganizationFlags organizationFlags; + private final DefaultGroupCreator defaultGroupCreator; + private final DefaultGroupFinder defaultGroupFinder; + private final RuleIndexer ruleIndexer; + + public OrganisationSupport(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, + OrganizationFlags organizationFlags, DefaultGroupCreator defaultGroupCreator, DefaultGroupFinder defaultGroupFinder, + RuleIndexer ruleIndexer) { + this.dbClient = dbClient; + this.defaultOrganizationProvider = defaultOrganizationProvider; + this.organizationFlags = organizationFlags; + this.defaultGroupCreator = defaultGroupCreator; + this.defaultGroupFinder = defaultGroupFinder; + this.ruleIndexer = ruleIndexer; + } + + public void enable(String login) { + String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid(); + try (DbSession dbSession = dbClient.openSession(false)) { + if (!organizationFlags.isEnabled(dbSession)) { + flagAdminUserAsRoot(dbSession, login); + createDefaultMembersGroup(dbSession, defaultOrganizationUuid); + List disabledTemplateAndCustomRuleIds = disableTemplateRulesAndCustomRules(dbSession); + enableFeature(dbSession); + ruleIndexer.commitAndIndex(dbSession, disabledTemplateAndCustomRuleIds); + } + } + } + + private void flagAdminUserAsRoot(DbSession dbSession, String login) { + dbClient.userDao().setRoot(dbSession, login, true); + } + + private void createDefaultMembersGroup(DbSession dbSession, String defaultOrganizationUuid) { + GroupDto sonarUsersGroupId = defaultGroupFinder.findDefaultGroup(dbSession, defaultOrganizationUuid); + GroupDto members = defaultGroupCreator.create(dbSession, defaultOrganizationUuid); + copySonarUsersGroupPermissionsToMembersGroup(dbSession, defaultOrganizationUuid, sonarUsersGroupId, members); + copySonarUsersGroupPermissionTemplatesToMembersGroup(dbSession, sonarUsersGroupId, members); + associateMembersOfDefaultOrganizationToGroup(dbSession, defaultOrganizationUuid, members); + } + + private void associateMembersOfDefaultOrganizationToGroup(DbSession dbSession, String defaultOrganizationUuid, GroupDto membersGroup) { + List organizationMembers = dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, defaultOrganizationUuid); + organizationMembers.forEach(member -> dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setGroupId(membersGroup.getId()).setUserId(member))); + } + + private void copySonarUsersGroupPermissionsToMembersGroup(DbSession dbSession, String defaultOrganizationUuid, GroupDto sonarUsersGroup, GroupDto membersGroup) { + dbClient.groupPermissionDao().selectAllPermissionsByGroupId(dbSession, defaultOrganizationUuid, sonarUsersGroup.getId(), + context -> { + GroupPermissionDto groupPermissionDto = (GroupPermissionDto) context.getResultObject(); + dbClient.groupPermissionDao().insert(dbSession, + new GroupPermissionDto().setOrganizationUuid(defaultOrganizationUuid).setGroupId(membersGroup.getId()) + .setRole(groupPermissionDto.getRole()) + .setResourceId(groupPermissionDto.getResourceId())); + }); + } + + private void copySonarUsersGroupPermissionTemplatesToMembersGroup(DbSession dbSession, GroupDto sonarUsersGroup, GroupDto membersGroup) { + List sonarUsersPermissionTemplates = dbClient.permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbSession, + sonarUsersGroup.getId()); + sonarUsersPermissionTemplates.forEach(permissionTemplateGroup -> dbClient.permissionTemplateDao().insertGroupPermission(dbSession, + permissionTemplateGroup.getTemplateId(), membersGroup.getId(), permissionTemplateGroup.getPermission())); + } + + private List disableTemplateRulesAndCustomRules(DbSession dbSession) { + List rules = dbClient.ruleDao().selectAllDefinitions(dbSession).stream() + .filter(r -> r.isTemplate() || r.isCustomRule()) + .collect(toList()); + rules.forEach(r -> { + r.setStatus(RuleStatus.REMOVED); + dbClient.ruleDao().update(dbSession, r); + }); + return rules.stream().map(RuleDefinitionDto::getId).collect(toList()); + } + + private void enableFeature(DbSession dbSession) { + organizationFlags.enable(dbSession); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/EnableSupportAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/EnableSupportAction.java index 8ffd1bf865a..92b25f395bb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/EnableSupportAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/EnableSupportAction.java @@ -19,50 +19,28 @@ */ package org.sonar.server.organization.ws; -import java.util.List; -import org.sonar.api.rule.RuleStatus; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.permission.GroupPermissionDto; import org.sonar.db.permission.OrganizationPermission; -import org.sonar.db.permission.template.PermissionTemplateGroupDto; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.db.user.GroupDto; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.organization.DefaultOrganizationProvider; -import org.sonar.server.organization.OrganizationFlags; -import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.organization.OrganisationSupport; import org.sonar.server.user.UserSession; -import org.sonar.server.usergroups.DefaultGroupCreator; -import org.sonar.server.usergroups.DefaultGroupFinder; import static java.util.Objects.requireNonNull; -import static org.sonar.core.util.stream.MoreCollectors.toList; public class EnableSupportAction implements OrganizationsWsAction { private static final String ACTION = "enable_support"; private final UserSession userSession; - private final DbClient dbClient; private final DefaultOrganizationProvider defaultOrganizationProvider; - private final OrganizationFlags organizationFlags; - private final DefaultGroupCreator defaultGroupCreator; - private final DefaultGroupFinder defaultGroupFinder; - private final RuleIndexer ruleIndexer; + private final OrganisationSupport organisationSupport; - public EnableSupportAction(UserSession userSession, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, - OrganizationFlags organizationFlags, DefaultGroupCreator defaultGroupCreator, DefaultGroupFinder defaultGroupFinder, RuleIndexer ruleIndexer) { + public EnableSupportAction(UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider, OrganisationSupport organisationSupport) { this.userSession = userSession; - this.dbClient = dbClient; this.defaultOrganizationProvider = defaultOrganizationProvider; - this.organizationFlags = organizationFlags; - this.defaultGroupCreator = defaultGroupCreator; - this.defaultGroupFinder = defaultGroupFinder; - this.ruleIndexer = ruleIndexer; + this.organisationSupport = organisationSupport; } @Override @@ -81,16 +59,8 @@ public class EnableSupportAction implements OrganizationsWsAction { @Override public void handle(Request request, Response response) throws Exception { verifySystemAdministrator(); - - try (DbSession dbSession = dbClient.openSession(false)) { - if (isSupportDisabled(dbSession)) { - flagCurrentUserAsRoot(dbSession); - createDefaultMembersGroup(dbSession); - List disabledTemplateAndCustomRuleIds = disableTemplateRulesAndCustomRules(dbSession); - enableFeature(dbSession); - ruleIndexer.commitAndIndex(dbSession, disabledTemplateAndCustomRuleIds); - } - } + + organisationSupport.enable(requireNonNull(userSession.getLogin())); response.noContent(); } @@ -98,60 +68,4 @@ public class EnableSupportAction implements OrganizationsWsAction { userSession.checkLoggedIn().checkPermission(OrganizationPermission.ADMINISTER, defaultOrganizationProvider.get().getUuid()); } - private boolean isSupportDisabled(DbSession dbSession) { - return !organizationFlags.isEnabled(dbSession); - } - - private void flagCurrentUserAsRoot(DbSession dbSession) { - dbClient.userDao().setRoot(dbSession, requireNonNull(userSession.getLogin()), true); - } - - private void createDefaultMembersGroup(DbSession dbSession) { - String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid(); - GroupDto sonarUsersGroupId = defaultGroupFinder.findDefaultGroup(dbSession, defaultOrganizationUuid); - GroupDto members = defaultGroupCreator.create(dbSession, defaultOrganizationUuid); - copySonarUsersGroupPermissionsToMembersGroup(dbSession, sonarUsersGroupId, members); - copySonarUsersGroupPermissionTemplatesToMembersGroup(dbSession, sonarUsersGroupId, members); - associateMembersOfDefaultOrganizationToGroup(dbSession, members); - } - - private void associateMembersOfDefaultOrganizationToGroup(DbSession dbSession, GroupDto membersGroup) { - List organizationMembers = dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, defaultOrganizationProvider.get().getUuid()); - organizationMembers.forEach(member -> dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setGroupId(membersGroup.getId()).setUserId(member))); - } - - private void copySonarUsersGroupPermissionsToMembersGroup(DbSession dbSession, GroupDto sonarUsersGroup, GroupDto membersGroup) { - String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid(); - dbClient.groupPermissionDao().selectAllPermissionsByGroupId(dbSession, defaultOrganizationUuid, sonarUsersGroup.getId(), - context -> { - GroupPermissionDto groupPermissionDto = (GroupPermissionDto) context.getResultObject(); - dbClient.groupPermissionDao().insert(dbSession, - new GroupPermissionDto().setOrganizationUuid(defaultOrganizationUuid).setGroupId(membersGroup.getId()) - .setRole(groupPermissionDto.getRole()) - .setResourceId(groupPermissionDto.getResourceId())); - }); - } - - private void copySonarUsersGroupPermissionTemplatesToMembersGroup(DbSession dbSession, GroupDto sonarUsersGroup, GroupDto membersGroup) { - List sonarUsersPermissionTemplates = dbClient.permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbSession, - sonarUsersGroup.getId()); - sonarUsersPermissionTemplates.forEach(permissionTemplateGroup -> dbClient.permissionTemplateDao().insertGroupPermission(dbSession, - permissionTemplateGroup.getTemplateId(), membersGroup.getId(), permissionTemplateGroup.getPermission())); - } - - public List disableTemplateRulesAndCustomRules(DbSession dbSession) { - List rules = dbClient.ruleDao().selectAllDefinitions(dbSession).stream() - .filter(r -> r.isTemplate() || r.isCustomRule()) - .collect(toList()); - rules.forEach(r -> { - r.setStatus(RuleStatus.REMOVED); - dbClient.ruleDao().update(dbSession, r); - }); - return rules.stream().map(RuleDefinitionDto::getId).collect(toList()); - } - - private void enableFeature(DbSession dbSession) { - organizationFlags.enable(dbSession); - } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java index 629674ff0d9..98616286efc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java @@ -21,6 +21,7 @@ package org.sonar.server.organization.ws; import org.sonar.api.config.Configuration; import org.sonar.core.platform.Module; +import org.sonar.server.organization.OrganisationSupport; import static org.sonar.process.ProcessProperties.Property.SONARCLOUD_ENABLED; @@ -44,6 +45,7 @@ public class OrganizationsWsModule extends Module { UpdateProjectVisibilityAction.class); if (config.getBoolean(SONARCLOUD_ENABLED.getKey()).orElse(false)) { add( + OrganisationSupport.class, EnableSupportAction.class, AddMemberAction.class, CreateAction.class, diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java new file mode 100644 index 00000000000..d15b681c226 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganisationSupportTest.java @@ -0,0 +1,219 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.organization; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.ArgumentCaptor; +import org.sonar.api.rule.RuleStatus; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.GroupPermissionDto; +import org.sonar.db.permission.template.PermissionTemplateDto; +import org.sonar.db.permission.template.PermissionTemplateGroupDto; +import org.sonar.db.rule.RuleDefinitionDto; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.UserDto; +import org.sonar.server.es.EsTester; +import org.sonar.server.rule.index.RuleIndexer; +import org.sonar.server.usergroups.DefaultGroupCreatorImpl; +import org.sonar.server.usergroups.DefaultGroupFinder; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +public class OrganisationSupportTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public DbTester dbTester = DbTester.create(); + @Rule + public EsTester es = EsTester.create(); + + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); + private OrganizationFlags organizationFlags = new OrganizationFlagsImpl(dbTester.getDbClient()); + private RuleIndexer ruleIndexer = spy(new RuleIndexer(es.client(), dbTester.getDbClient())); + private OrganisationSupport underTest = new OrganisationSupport(dbTester.getDbClient(), defaultOrganizationProvider, organizationFlags, + new DefaultGroupCreatorImpl(dbTester.getDbClient()), new DefaultGroupFinder(dbTester.getDbClient()), ruleIndexer); + + @Test + public void enabling_support_saves_internal_property_and_flags_caller_as_root() { + UserDto user = dbTester.users().insertUser(); + UserDto otherUser = dbTester.users().insertUser(); + dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); + verifyFeatureEnabled(false); + verifyRoot(user, false); + verifyRoot(otherUser, false); + + call(user.getLogin()); + + verifyFeatureEnabled(true); + verifyRoot(user, true); + verifyRoot(otherUser, false); + } + + @Test + public void enabling_support_creates_default_members_group_and_associate_org_members() { + OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); + OrganizationDto anotherOrganization = dbTester.organizations().insert(); + UserDto user1 = dbTester.users().insertUser(); + UserDto user2 = dbTester.users().insertUser(); + UserDto userInAnotherOrganization = dbTester.users().insertUser(); + dbTester.organizations().addMember(defaultOrganization, user1); + dbTester.organizations().addMember(defaultOrganization, user2); + dbTester.organizations().addMember(anotherOrganization, userInAnotherOrganization); + dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); + + call(user1.getLogin()); + + Optional defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()); + assertThat(defaultGroupId).isPresent(); + GroupDto membersGroup = dbTester.getDbClient().groupDao().selectById(dbTester.getSession(), defaultGroupId.get()); + assertThat(membersGroup).isNotNull(); + assertThat(membersGroup.getName()).isEqualTo("Members"); + assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user1.getId())).containsOnly(defaultGroupId.get()); + assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user2.getId())).containsOnly(defaultGroupId.get()); + assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), userInAnotherOrganization.getId())).isEmpty(); + } + + @Test + public void enabling_support_copy_sonar_users_permissions_to_members_group() { + OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); + UserDto user = dbTester.users().insertUser(); + GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users"); + ComponentDto project = dbTester.components().insertPrivateProject(defaultOrganization); + dbTester.users().insertPermissionOnGroup(sonarUsersGroup, "user"); + dbTester.users().insertProjectPermissionOnGroup(sonarUsersGroup, "codeviewer", project); + // Should be ignored + GroupDto anotherGroup = dbTester.users().insertGroup(); + dbTester.users().insertPermissionOnGroup(anotherGroup, "admin"); + + call(user.getLogin()); + + int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get(); + assertThat(defaultGroupId).isNotEqualTo(sonarUsersGroup.getId()); + List result = new ArrayList<>(); + dbTester.getDbClient().groupPermissionDao().selectAllPermissionsByGroupId(dbTester.getSession(), defaultOrganization.getUuid(), defaultGroupId, + context -> result.add((GroupPermissionDto) context.getResultObject())); + assertThat(result).extracting(GroupPermissionDto::getResourceId, GroupPermissionDto::getRole).containsOnly( + tuple(null, "user"), tuple(project.getId(), "codeviewer")); + } + + @Test + public void enabling_support_copy_sonar_users_permission_templates_to_members_group() { + OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); + UserDto user = dbTester.users().insertUser(); + GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users"); + PermissionTemplateDto permissionTemplate = dbTester.permissionTemplates().insertTemplate(dbTester.getDefaultOrganization()); + dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "user"); + dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "admin"); + // Should be ignored + GroupDto otherGroup = dbTester.users().insertGroup(); + dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, otherGroup, "user"); + + call(user.getLogin()); + + int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get(); + assertThat(dbTester.getDbClient().permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbTester.getSession(), defaultGroupId)) + .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission) + .containsOnly(tuple(defaultGroupId, "user"), tuple(defaultGroupId, "admin")); + } + + @Test + public void enabling_organizations_should_remove_template_rule_and_custom_rule() { + RuleDefinitionDto normal = dbTester.rules().insert(); + RuleDefinitionDto template = dbTester.rules().insert(r -> r.setIsTemplate(true)); + RuleDefinitionDto custom = dbTester.rules().insert(r -> r.setTemplateId(template.getId())); + + UserDto user = dbTester.users().insertUser(); + dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); + + assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession())) + .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus) + .containsExactlyInAnyOrder( + tuple(normal.getKey(), RuleStatus.READY), + tuple(template.getKey(), RuleStatus.READY), + tuple(custom.getKey(), RuleStatus.READY)); + + call(user.getLogin()); + + assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession())) + .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus) + .containsExactlyInAnyOrder( + tuple(normal.getKey(), RuleStatus.READY), + tuple(template.getKey(), RuleStatus.REMOVED), + tuple(custom.getKey(), RuleStatus.REMOVED)); + + @SuppressWarnings("unchecked") + Class> listClass = (Class>) (Class) ArrayList.class; + ArgumentCaptor> indexedRuleKeys = ArgumentCaptor.forClass(listClass); + verify(ruleIndexer).commitAndIndex(any(), indexedRuleKeys.capture()); + assertThat(indexedRuleKeys.getValue()).containsExactlyInAnyOrder(template.getId(), custom.getId()); + } + + @Test + public void throw_IAE_when_members_group_already_exists() { + UserDto user = dbTester.users().insertUser(); + dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); + dbTester.users().insertGroup(dbTester.getDefaultOrganization(), "Members"); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The group 'Members' already exist"); + + call(user.getLogin()); + } + + @Test + public void do_nothing_if_support_is_already_enabled() { + dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); + + call("foo"); + verifyFeatureEnabled(true); + + // the test could be improved to verify that + // the caller user is not flagged as root + // if he was not already root + call("foo"); + verifyFeatureEnabled(true); + } + + private void call(String login) { + underTest.enable(login); + } + + private void verifyFeatureEnabled(boolean enabled) { + assertThat(organizationFlags.isEnabled(dbTester.getSession())).isEqualTo(enabled); + } + + private void verifyRoot(UserDto user, boolean root) { + dbTester.rootFlag().verify(user.getLogin(), root); + } + + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/EnableSupportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/EnableSupportActionTest.java index fdd91d53680..9fff8f4213c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/EnableSupportActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/EnableSupportActionTest.java @@ -20,42 +20,25 @@ package org.sonar.server.organization.ws; import java.net.HttpURLConnection; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.sonar.api.rule.RuleStatus; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.GroupPermissionDto; -import org.sonar.db.permission.template.PermissionTemplateDto; -import org.sonar.db.permission.template.PermissionTemplateGroupDto; -import org.sonar.db.rule.RuleDefinitionDto; -import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.server.es.EsTester; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.organization.DefaultOrganizationProvider; -import org.sonar.server.organization.OrganizationFlags; -import org.sonar.server.organization.OrganizationFlagsImpl; +import org.sonar.server.organization.OrganisationSupport; import org.sonar.server.organization.TestDefaultOrganizationProvider; -import org.sonar.server.rule.index.RuleIndexer; import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.usergroups.DefaultGroupCreatorImpl; -import org.sonar.server.usergroups.DefaultGroupFinder; import org.sonar.server.ws.TestResponse; import org.sonar.server.ws.WsActionTester; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; @@ -71,143 +54,19 @@ public class EnableSupportActionTest { public EsTester es = EsTester.create(); private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); - private OrganizationFlags organizationFlags = new OrganizationFlagsImpl(dbTester.getDbClient()); - private RuleIndexer ruleIndexer = spy(new RuleIndexer(es.client(), dbTester.getDbClient())); - private EnableSupportAction underTest = new EnableSupportAction(userSession, dbTester.getDbClient(), defaultOrganizationProvider, organizationFlags, - new DefaultGroupCreatorImpl(dbTester.getDbClient()), new DefaultGroupFinder(dbTester.getDbClient()), ruleIndexer); + private OrganisationSupport organisationSupport = mock(OrganisationSupport.class); + private EnableSupportAction underTest = new EnableSupportAction(userSession, defaultOrganizationProvider, organisationSupport); private WsActionTester tester = new WsActionTester(underTest); @Test public void enabling_support_saves_internal_property_and_flags_caller_as_root() { UserDto user = dbTester.users().insertUser(); UserDto otherUser = dbTester.users().insertUser(); - dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); - verifyFeatureEnabled(false); - verifyRoot(user, false); - verifyRoot(otherUser, false); - logInAsSystemAdministrator(user.getLogin()); - - call(); - - verifyFeatureEnabled(true); - verifyRoot(user, true); - verifyRoot(otherUser, false); - } - - @Test - public void enabling_support_creates_default_members_group_and_associate_org_members() { - OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); - OrganizationDto anotherOrganization = dbTester.organizations().insert(); - UserDto user1 = dbTester.users().insertUser(); - UserDto user2 = dbTester.users().insertUser(); - UserDto userInAnotherOrganization = dbTester.users().insertUser(); - dbTester.organizations().addMember(defaultOrganization, user1); - dbTester.organizations().addMember(defaultOrganization, user2); - dbTester.organizations().addMember(anotherOrganization, userInAnotherOrganization); - dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); - logInAsSystemAdministrator(user1.getLogin()); - - call(); - - Optional defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()); - assertThat(defaultGroupId).isPresent(); - GroupDto membersGroup = dbTester.getDbClient().groupDao().selectById(dbTester.getSession(), defaultGroupId.get()); - assertThat(membersGroup).isNotNull(); - assertThat(membersGroup.getName()).isEqualTo("Members"); - assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user1.getId())).containsOnly(defaultGroupId.get()); - assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), user2.getId())).containsOnly(defaultGroupId.get()); - assertThat(dbTester.getDbClient().groupMembershipDao().selectGroupIdsByUserId(dbTester.getSession(), userInAnotherOrganization.getId())).isEmpty(); - } - - @Test - public void enabling_support_copy_sonar_users_permissions_to_members_group() { - OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); - UserDto user = dbTester.users().insertUser(); - GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users"); - ComponentDto project = dbTester.components().insertPrivateProject(defaultOrganization); - dbTester.users().insertPermissionOnGroup(sonarUsersGroup, "user"); - dbTester.users().insertProjectPermissionOnGroup(sonarUsersGroup, "codeviewer", project); - // Should be ignored - GroupDto anotherGroup = dbTester.users().insertGroup(); - dbTester.users().insertPermissionOnGroup(anotherGroup, "admin"); - logInAsSystemAdministrator(user.getLogin()); - - call(); - - int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get(); - assertThat(defaultGroupId).isNotEqualTo(sonarUsersGroup.getId()); - List result = new ArrayList<>(); - dbTester.getDbClient().groupPermissionDao().selectAllPermissionsByGroupId(dbTester.getSession(), defaultOrganization.getUuid(), defaultGroupId, - context -> result.add((GroupPermissionDto) context.getResultObject())); - assertThat(result).extracting(GroupPermissionDto::getResourceId, GroupPermissionDto::getRole).containsOnly( - tuple(null, "user"), tuple(project.getId(), "codeviewer")); - } - - @Test - public void enabling_support_copy_sonar_users_permission_templates_to_members_group() { - OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); - UserDto user = dbTester.users().insertUser(); - GroupDto sonarUsersGroup = dbTester.users().insertDefaultGroup(defaultOrganization, "sonar-users"); - PermissionTemplateDto permissionTemplate = dbTester.permissionTemplates().insertTemplate(dbTester.getDefaultOrganization()); - dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "user"); - dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, sonarUsersGroup, "admin"); - // Should be ignored - GroupDto otherGroup = dbTester.users().insertGroup(); - dbTester.permissionTemplates().addGroupToTemplate(permissionTemplate, otherGroup, "user"); - logInAsSystemAdministrator(user.getLogin()); - - call(); - - int defaultGroupId = dbTester.getDbClient().organizationDao().getDefaultGroupId(dbTester.getSession(), defaultOrganization.getUuid()).get(); - assertThat(dbTester.getDbClient().permissionTemplateDao().selectAllGroupPermissionTemplatesByGroupId(dbTester.getSession(), defaultGroupId)) - .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission) - .containsOnly(tuple(defaultGroupId, "user"), tuple(defaultGroupId, "admin")); - } - - @Test - public void enabling_organizations_should_remove_template_rule_and_custom_rule() { - RuleDefinitionDto normal = dbTester.rules().insert(); - RuleDefinitionDto template = dbTester.rules().insert(r -> r.setIsTemplate(true)); - RuleDefinitionDto custom = dbTester.rules().insert(r -> r.setTemplateId(template.getId())); - - UserDto user = dbTester.users().insertUser(); - dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); logInAsSystemAdministrator(user.getLogin()); - assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession())) - .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus) - .containsExactlyInAnyOrder( - tuple(normal.getKey(), RuleStatus.READY), - tuple(template.getKey(), RuleStatus.READY), - tuple(custom.getKey(), RuleStatus.READY)); - call(); - assertThat(dbTester.getDbClient().ruleDao().selectAllDefinitions(dbTester.getSession())) - .extracting(RuleDefinitionDto::getKey, RuleDefinitionDto::getStatus) - .containsExactlyInAnyOrder( - tuple(normal.getKey(), RuleStatus.READY), - tuple(template.getKey(), RuleStatus.REMOVED), - tuple(custom.getKey(), RuleStatus.REMOVED)); - - @SuppressWarnings("unchecked") - Class> listClass = (Class>) (Class) ArrayList.class; - ArgumentCaptor> indexedRuleKeys = ArgumentCaptor.forClass(listClass); - verify(ruleIndexer).commitAndIndex(any(), indexedRuleKeys.capture()); - assertThat(indexedRuleKeys.getValue()).containsExactlyInAnyOrder(template.getId(), custom.getId()); - } - - @Test - public void throw_IAE_when_members_group_already_exists() { - UserDto user = dbTester.users().insertUser(); - dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); - dbTester.users().insertGroup(dbTester.getDefaultOrganization(), "Members"); - logInAsSystemAdministrator(user.getLogin()); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("The group 'Members' already exist"); - - call(); + verify(organisationSupport).enable(user.getLogin()); } @Test @@ -231,29 +90,16 @@ public class EnableSupportActionTest { } @Test - public void throw_ISE_when_default_organization_has_not_default_group() { - UserDto user = dbTester.users().insertUser(); - logInAsSystemAdministrator(user.getLogin()); - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(String.format("Default group cannot be found on organization '%s'", defaultOrganizationProvider.get().getUuid())); - - call(); - } - - @Test - public void do_nothing_if_support_is_already_enabled() { + public void call_delegate_even_if_support_is_already_enabled() { dbTester.users().insertDefaultGroup(dbTester.getDefaultOrganization(), "sonar-users"); logInAsSystemAdministrator("foo"); call(); - verifyFeatureEnabled(true); + verify(organisationSupport).enable("foo"); + reset(organisationSupport); - // the test could be improved to verify that - // the caller user is not flagged as root - // if he was not already root call(); - verifyFeatureEnabled(true); + verify(organisationSupport).enable("foo"); } @Test @@ -274,11 +120,4 @@ public class EnableSupportActionTest { assertThat(response.getStatus()).isEqualTo(HttpURLConnection.HTTP_NO_CONTENT); } - private void verifyFeatureEnabled(boolean enabled) { - assertThat(organizationFlags.isEnabled(dbTester.getSession())).isEqualTo(enabled); - } - - private void verifyRoot(UserDto user, boolean root) { - dbTester.rootFlag().verify(user.getLogin(), root); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/OrganizationsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/OrganizationsWsModuleTest.java index 7f694da13de..57f01dd1e4a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/OrganizationsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/OrganizationsWsModuleTest.java @@ -49,7 +49,7 @@ public class OrganizationsWsModuleTest { underTest.configure(container); assertThat(container.getPicoContainer().getComponentAdapters()) - .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 11); + .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 12); } } -- 2.39.5