From 981424daf18ee985438af28344b562d2471f3a50 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 26 May 2017 11:42:49 +0200 Subject: [PATCH] SONAR-8888 index active rules when creating organization --- .../it/organization/OrganizationTest.java | 73 ++++++++++++++----- .../OrganizationCreationImpl.java | 7 +- .../MassRegisterQualityProfiles.java | 2 +- .../OrganizationCreationImplTest.java | 5 +- .../organization/ws/CreateActionTest.java | 4 +- .../QualityProfilesService.java | 3 +- 6 files changed, 69 insertions(+), 25 deletions(-) diff --git a/it/it-tests/src/test/java/it/organization/OrganizationTest.java b/it/it-tests/src/test/java/it/organization/OrganizationTest.java index 6c998d8fb6b..a9de4924d88 100644 --- a/it/it-tests/src/test/java/it/organization/OrganizationTest.java +++ b/it/it-tests/src/test/java/it/organization/OrganizationTest.java @@ -23,6 +23,7 @@ import com.sonar.orchestrator.Orchestrator; import com.sonar.orchestrator.build.BuildFailureException; import it.Category6Suite; import java.util.List; +import java.util.Locale; import java.util.function.Consumer; import java.util.function.Function; import org.junit.After; @@ -33,6 +34,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonarqube.ws.Organizations; +import org.sonarqube.ws.QualityProfiles; +import org.sonarqube.ws.Rules; import org.sonarqube.ws.WsComponents; import org.sonarqube.ws.WsUsers; import org.sonarqube.ws.client.HttpException; @@ -103,7 +106,7 @@ public class OrganizationTest { @Test public void create_update_delete_organizations_and_check_security() { - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(KEY); Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder() .setName(NAME) @@ -120,6 +123,7 @@ public class OrganizationTest { assertThat(createdOrganization.getAvatar()).isEqualTo(AVATAR_URL); verifySingleSearchResult(createdOrganization, NAME, DESCRIPTION, URL, AVATAR_URL); + assertThatBuiltInQualityProfilesExist(createdOrganization.getKey()); // update by id adminOrganizationService.update(new UpdateWsRequest.Builder() @@ -153,7 +157,8 @@ public class OrganizationTest { // delete organization adminOrganizationService.delete(createdOrganization.getKey()); - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(createdOrganization.getKey()); + assertThatQualityProfilesDoNotExist(createdOrganization.getKey()); adminOrganizationService.create(new CreateWsRequest.Builder() .setName(NAME) @@ -164,24 +169,24 @@ public class OrganizationTest { // verify anonymous can't create update nor delete an organization by default verifyAnonymousNotAuthorized(service -> service.create(new CreateWsRequest.Builder().setName("An org").build())); - verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); - verifyUserNotAuthenticated(service -> service.delete(KEY)); + assertThatUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); + assertThatUserNotAuthenticated(service -> service.delete(KEY)); // verify logged in user without any permission can't create update nor delete an organization by default userRule.createUser(USER_LOGIN, USER_LOGIN); - verifyUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.create(new CreateWsRequest.Builder().setName("An org").build())); - verifyUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); - verifyUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.delete(KEY)); + assertThatUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.create(new CreateWsRequest.Builder().setName("An org").build())); + assertThatUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); + assertThatUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.delete(KEY)); setServerProperty(orchestrator, SETTING_ANYONE_CAN_CREATE_ORGANIZATIONS, "true"); // verify anonymous still can't create update nor delete an organization if property is true - verifyUserNotAuthenticated(service -> service.create(new CreateWsRequest.Builder().setName("An org").build())); - verifyUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); - verifyUserNotAuthenticated(service -> service.delete(KEY)); + assertThatUserNotAuthenticated(service -> service.create(new CreateWsRequest.Builder().setName("An org").build())); + assertThatUserNotAuthenticated(service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); + assertThatUserNotAuthenticated(service -> service.delete(KEY)); // verify logged in user without any permission can't create nor update nor delete an organization if property is true - verifyUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); - verifyUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.delete(KEY)); + assertThatUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.update(new UpdateWsRequest.Builder().setKey(KEY).setName("new name").build())); + assertThatUserNotAuthorized(USER_LOGIN, USER_LOGIN, service -> service.delete(KEY)); // clean-up adminOrganizationService.delete(KEY); verifySingleSearchResult( @@ -198,7 +203,7 @@ public class OrganizationTest { } } - private void verifyUserNotAuthenticated(Consumer consumer) { + private void assertThatUserNotAuthenticated(Consumer consumer) { try { consumer.accept(anonymousOrganizationService); fail("An HttpException should have been raised"); @@ -207,7 +212,7 @@ public class OrganizationTest { } } - private void verifyUserNotAuthorized(String login, String password, Consumer consumer) { + private void assertThatUserNotAuthorized(String login, String password, Consumer consumer) { try { OrganizationService organizationService = newUserWsClient(orchestrator, login, password).organizations(); consumer.accept(organizationService); @@ -270,7 +275,7 @@ public class OrganizationTest { @Test public void an_organization_member_can_analyze_project() { - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(KEY); Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder() .setName(KEY) @@ -292,7 +297,7 @@ public class OrganizationTest { @Test public void by_default_anonymous_cannot_analyse_project_on_organization() { - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(KEY); Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder() .setName(KEY) @@ -337,7 +342,7 @@ public class OrganizationTest { @Test public void deleting_an_organization_also_deletes_projects_and_check_security() { - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(KEY); Organizations.Organization createdOrganization = adminOrganizationService.create(new CreateWsRequest.Builder() .setName(KEY) @@ -366,7 +371,7 @@ public class OrganizationTest { adminOrganizationService.delete(KEY); expect404HttpError(() -> searchSampleProject(KEY, componentsService)); - verifyOrganizationDoesNotExit(KEY); + assertThatOrganizationDoesNotExit(KEY); } @Test @@ -417,7 +422,7 @@ public class OrganizationTest { } } - private void verifyOrganizationDoesNotExit(String organizationKey) { + private void assertThatOrganizationDoesNotExit(String organizationKey) { Organizations.SearchWsResponse searchWsResponse = anonymousOrganizationService.search(new SearchWsRequest.Builder().setOrganizations(organizationKey).build()); assertThat(searchWsResponse.getOrganizationsList()).isEmpty(); } @@ -446,4 +451,34 @@ public class OrganizationTest { assertThat(searchedOrganization.getAvatar()).isEqualTo(avatarUrl); } } + + private void assertThatBuiltInQualityProfilesExist(String organizationKey) { + org.sonarqube.ws.client.qualityprofile.SearchWsRequest profilesRequest = new org.sonarqube.ws.client.qualityprofile.SearchWsRequest().setOrganizationKey(organizationKey); + QualityProfiles.SearchWsResponse response = adminClient.qualityProfiles().search(profilesRequest); + assertThat(response.getProfilesCount()).isGreaterThan(0); + for (QualityProfiles.SearchWsResponse.QualityProfile profile : response.getProfilesList()) { + assertThat(profile.getIsInherited()).isFalse(); + assertThat(profile.getProjectCount()).isEqualTo(0); + if (profile.getName().toLowerCase(Locale.ENGLISH).contains("empty")) { + assertThat(profile.getActiveRuleCount()).isEqualTo(0); + } else { + assertThat(profile.getActiveRuleCount()).isGreaterThan(0); + // that allows to check the Elasticsearch index of active rules + Rules.SearchResponse activeRulesResponse = adminClient.rules().search(new org.sonarqube.ws.client.rule.SearchWsRequest().setActivation(true).setQProfile(profile.getKey())); + assertThat(activeRulesResponse.getTotal()).isEqualTo(profile.getActiveRuleCount()); + assertThat(activeRulesResponse.getRulesCount()).isEqualTo((int)profile.getActiveRuleCount()); + } + } + } + + private void assertThatQualityProfilesDoNotExist(String organizationKey) { + org.sonarqube.ws.client.qualityprofile.SearchWsRequest profilesRequest = new org.sonarqube.ws.client.qualityprofile.SearchWsRequest().setOrganizationKey(organizationKey); + try { + adminClient.qualityProfiles().search(profilesRequest); + fail(); + } catch (HttpException e) { + assertThat(e.code()).isEqualTo(404); + assertThat(e.getMessage()).contains("No organization with key '" + organizationKey + "'"); + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java index 327d9bd76d1..e588c4314a0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java @@ -45,6 +45,7 @@ import org.sonar.db.user.UserGroupDto; import org.sonar.server.qualityprofile.DefinedQProfile; import org.sonar.server.qualityprofile.DefinedQProfileInsert; import org.sonar.server.qualityprofile.DefinedQProfileRepository; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; import org.sonar.server.user.index.UserIndexer; import org.sonar.server.usergroups.DefaultGroupCreator; @@ -70,11 +71,12 @@ public class OrganizationCreationImpl implements OrganizationCreation { private final DefinedQProfileInsert definedQProfileInsert; private final DefaultGroupCreator defaultGroupCreator; private final UserIndexer userIndexer; + private final ActiveRuleIndexer activeRuleIndexer; public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, OrganizationValidation organizationValidation, Settings settings, UserIndexer userIndexer, DefinedQProfileRepository definedQProfileRepository, DefinedQProfileInsert definedQProfileInsert, - DefaultGroupCreator defaultGroupCreator) { + DefaultGroupCreator defaultGroupCreator, ActiveRuleIndexer activeRuleIndexer) { this.dbClient = dbClient; this.system2 = system2; this.uuidFactory = uuidFactory; @@ -84,6 +86,7 @@ public class OrganizationCreationImpl implements OrganizationCreation { this.definedQProfileRepository = definedQProfileRepository; this.definedQProfileInsert = definedQProfileInsert; this.defaultGroupCreator = defaultGroupCreator; + this.activeRuleIndexer = activeRuleIndexer; } @Override @@ -108,6 +111,7 @@ public class OrganizationCreationImpl implements OrganizationCreation { dbSession.commit(); batchDbSession.commit(); + activeRuleIndexer.index(); // Elasticsearch is updated when DB session is committed userIndexer.index(userCreator.getLogin()); @@ -146,6 +150,7 @@ public class OrganizationCreationImpl implements OrganizationCreation { dbSession.commit(); batchDbSession.commit(); + activeRuleIndexer.index(); // Elasticsearch is updated when DB session is committed userIndexer.index(newUser.getLogin()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/MassRegisterQualityProfiles.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/MassRegisterQualityProfiles.java index 25afdb1d836..8e449fd2f16 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/MassRegisterQualityProfiles.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/MassRegisterQualityProfiles.java @@ -99,7 +99,7 @@ public class MassRegisterQualityProfiles { } private void registerPerQualityProfileAndOrganization(DbSession session, DbSession batchSession, - DefinedQProfile definedQProfile, OrganizationDto organization, Profiler profiler) { + DefinedQProfile definedQProfile, OrganizationDto organization, Profiler profiler) { profiler.start(); definedQProfileInsert.create(session, batchSession, definedQProfile, organization); diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java index de7d31f798d..6144c27542d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java @@ -53,6 +53,7 @@ import org.sonar.server.qualityprofile.ActiveRuleChange; import org.sonar.server.qualityprofile.DefinedQProfile; import org.sonar.server.qualityprofile.DefinedQProfileInsertRule; import org.sonar.server.qualityprofile.DefinedQProfileRepositoryRule; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; import org.sonar.server.user.index.UserIndex; import org.sonar.server.user.index.UserIndexDefinition; import org.sonar.server.user.index.UserIndexer; @@ -107,9 +108,9 @@ public class OrganizationCreationImplTest { private UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); private UserIndex userIndex = new UserIndex(es.client()); private DefaultGroupCreator defaultGroupCreator = new DefaultGroupCreatorImpl(dbClient); - + private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); private OrganizationCreationImpl underTest = new OrganizationCreationImpl(dbClient, system2, uuidFactory, organizationValidation, settings, userIndexer, - definedQProfileRepositoryRule, definedQProfileCreationRule, defaultGroupCreator); + definedQProfileRepositoryRule, definedQProfileCreationRule, defaultGroupCreator, activeRuleIndexer); private UserDto someUser; diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java index a1b02e8f8ef..97c2c676528 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java @@ -57,6 +57,7 @@ import org.sonar.server.organization.OrganizationValidationImpl; import org.sonar.server.organization.TestOrganizationFlags; import org.sonar.server.qualityprofile.DefinedQProfileInsert; import org.sonar.server.qualityprofile.DefinedQProfileRepository; +import org.sonar.server.qualityprofile.index.ActiveRuleIndexer; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.index.UserIndex; import org.sonar.server.user.index.UserIndexDefinition; @@ -100,8 +101,9 @@ public class CreateActionTest { private OrganizationValidation organizationValidation = new OrganizationValidationImpl(); private UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); private UserIndex userIndex = new UserIndex(es.client()); + private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class); private OrganizationCreation organizationCreation = new OrganizationCreationImpl(dbClient, system2, uuidFactory, organizationValidation, settings, userIndexer, - mock(DefinedQProfileRepository.class), mock(DefinedQProfileInsert.class), new DefaultGroupCreatorImpl(dbClient)); + mock(DefinedQProfileRepository.class), mock(DefinedQProfileInsert.class), new DefaultGroupCreatorImpl(dbClient), activeRuleIndexer); private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone().setEnabled(true); private UserDto user; diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java index 6b874052273..9d3cf61c216 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualityprofile/QualityProfilesService.java @@ -74,7 +74,8 @@ public class QualityProfilesService extends BaseService { .setParam(PARAM_DEFAULTS, request.getDefaults()) .setParam(PARAM_LANGUAGE, request.getLanguage()) .setParam(PARAM_PROFILE_NAME, request.getProfileName()) - .setParam(PARAM_PROJECT_KEY, request.getProjectKey()), + .setParam(PARAM_PROJECT_KEY, request.getProjectKey()) + .setParam(PARAM_ORGANIZATION, request.getOrganizationKey()), SearchWsResponse.parser()); } -- 2.39.5