diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2017-03-21 17:58:25 +0100 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-03-23 17:38:34 +0100 |
commit | bd45c3888aef453bc5ff69d8e4db5d6ecab433f5 (patch) | |
tree | c257a080303dee68f691bcaab280ebca89974558 | |
parent | 442683e7b4097373eaf2c7ee51c5677601d24656 (diff) | |
download | sonarqube-bd45c3888aef453bc5ff69d8e4db5d6ecab433f5.tar.gz sonarqube-bd45c3888aef453bc5ff69d8e4db5d6ecab433f5.zip |
SONAR-8865 support new param "organization" in api/rules/app
5 files changed, 213 insertions, 85 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java index 522e0a4d139..fd5455c4e9c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/AppAction.java @@ -31,45 +31,54 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.qualityprofile.QualityProfileDto; -import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.server.user.UserSession; +import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION; + public class AppAction implements RulesWsAction { private final Languages languages; private final DbClient dbClient; private final I18n i18n; private final UserSession userSession; - private final DefaultOrganizationProvider defaultOrganizationProvider; + private final RuleWsSupport wsSupport; - public AppAction(Languages languages, DbClient dbClient, I18n i18n, UserSession userSession, - DefaultOrganizationProvider defaultOrganizationProvider) { + public AppAction(Languages languages, DbClient dbClient, I18n i18n, UserSession userSession, RuleWsSupport wsSupport) { this.languages = languages; this.dbClient = dbClient; this.i18n = i18n; this.userSession = userSession; - this.defaultOrganizationProvider = defaultOrganizationProvider; + this.wsSupport = wsSupport; } @Override public void define(WebService.NewController controller) { - controller.createAction("app") + WebService.NewAction action = controller.createAction("app") .setDescription("Get data required for rendering the page 'Coding Rules'.") .setResponseExample(getClass().getResource("app-example.json")) .setSince("4.5") .setInternal(true) .setHandler(this); + + action.createParam(PARAM_ORGANIZATION) + .setDescription("Organization key") + .setRequired(false) + .setInternal(true) + .setSince("6.4") + .setExampleValue("my-org"); } @Override public void handle(Request request, Response response) throws Exception { try (DbSession dbSession = dbClient.openSession(false)) { + OrganizationDto organization = wsSupport.getOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION)); + JsonWriter json = response.newJsonWriter(); json.beginObject(); - addPermissions(json); - addProfiles(json, dbSession); + addPermissions(organization, json); + addProfiles(dbSession, organization, json); addLanguages(json); addRuleRepositories(json, dbSession); addStatuses(json); @@ -77,14 +86,14 @@ public class AppAction implements RulesWsAction { } } - private void addPermissions(JsonWriter json) { - boolean canWrite = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid()); + private void addPermissions(OrganizationDto organization, JsonWriter json) { + boolean canWrite = userSession.hasPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization); json.prop("canWrite", canWrite); } - private void addProfiles(JsonWriter json, DbSession dbSession) { + private void addProfiles(DbSession dbSession, OrganizationDto organization, JsonWriter json) { json.name("qualityprofiles").beginArray(); - for (QualityProfileDto profile : dbClient.qualityProfileDao().selectAll(dbSession, getDefaultOrganization(dbSession))) { + for (QualityProfileDto profile : dbClient.qualityProfileDao().selectAll(dbSession, organization)) { if (languageIsSupported(profile)) { json .beginObject() @@ -131,11 +140,4 @@ public class AppAction implements RulesWsAction { } json.endObject(); } - - private OrganizationDto getDefaultOrganization(DbSession dbSession) { - String defaultOrganizationKey = defaultOrganizationProvider.get().getKey(); - return dbClient.organizationDao() - .selectByKey(dbSession, defaultOrganizationKey) - .orElseThrow(() -> new IllegalStateException("Cannot find default organization with key "+defaultOrganizationKey)); - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java index b0097e3bb73..27a14b2678a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RuleWsSupport.java @@ -19,18 +19,27 @@ */ package org.sonar.server.rule.ws; +import java.util.Optional; +import javax.annotation.Nullable; import org.sonar.api.server.ServerSide; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.user.UserSession; +import org.sonar.server.ws.WsUtils; import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; @ServerSide public class RuleWsSupport { + + private final DbClient dbClient; private final UserSession userSession; private final DefaultOrganizationProvider defaultOrganizationProvider; - public RuleWsSupport(UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) { + public RuleWsSupport(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) { + this.dbClient = dbClient; this.userSession = userSession; this.defaultOrganizationProvider = defaultOrganizationProvider; } @@ -40,4 +49,13 @@ public class RuleWsSupport { .checkLoggedIn() .checkPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid()); } + + public OrganizationDto getOrganizationByKey(DbSession dbSession, @Nullable String organizationKey) { + String organizationOrDefaultKey = Optional.ofNullable(organizationKey) + .orElseGet(defaultOrganizationProvider.get()::getKey); + return WsUtils.checkFoundWithOptional( + dbClient.organizationDao().selectByKey(dbSession, organizationOrDefaultKey), + "No organization with key '%s'", organizationOrDefaultKey); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java index f861a31338c..61fe819c81e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/AppActionTest.java @@ -22,68 +22,214 @@ package org.sonar.server.rule.ws; import java.util.Locale; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.sonar.api.i18n.I18n; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; +import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.OrganizationPermission; import org.sonar.db.qualityprofile.QualityProfileDto; import org.sonar.db.rule.RuleRepositoryDto; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.language.LanguageTesting; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.qualityprofile.QProfileTesting; import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.ws.WsTester; +import org.sonar.server.ws.WsActionTester; import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; +import static org.sonar.test.JsonAssert.assertJson; public class AppActionTest { + private static final Language LANG1 = LanguageTesting.newLanguage("xoo", "Xoo"); + private static final Language LANG2 = LanguageTesting.newLanguage("ws", "Whitespace"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone(); - private Languages languages = mock(Languages.class); + private Languages languages = new Languages(LANG1, LANG2); private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private I18n i18n = mock(I18n.class); + private RuleWsSupport wsSupport = new RuleWsSupport(db.getDbClient(), userSession, defaultOrganizationProvider); + private AppAction underTest = new AppAction(languages, db.getDbClient(), i18n, userSession, wsSupport); + private WsActionTester tester = new WsActionTester(underTest); @Test - public void should_generate_app_init_info() throws Exception { - AppAction app = new AppAction(languages, db.getDbClient(), i18n, userSessionRule, defaultOrganizationProvider); - WsTester tester = new WsTester(new RulesWs(app)); + public void test_definition() { + WebService.Action definition = tester.getDef(); - userSessionRule.addPermission(ADMINISTER_QUALITY_PROFILES, defaultOrganizationProvider.get().getUuid()); + assertThat(definition.isInternal()).isTrue(); + assertThat(definition.key()).isEqualTo("app"); + assertThat(definition.params()).hasSize(1); + assertThat(definition.param("organization")) + .matches(p -> p.isInternal()) + .matches(p -> p.since().equals("6.4")) + .matches(p -> !p.isRequired()); + } - QualityProfileDto profile1 = QProfileTesting.newXooP1(db.getDefaultOrganization()); - QualityProfileDto profile2 = QProfileTesting.newXooP2(db.getDefaultOrganization()).setParentKee(QProfileTesting.XOO_P1_KEY); - db.getDbClient().qualityProfileDao().insert(db.getSession(), profile1); - db.getDbClient().qualityProfileDao().insert(db.getSession(), profile2); - db.commit(); + @Test + public void response_contains_rule_repositories() { + insertRules(); + + String json = tester.newRequest().execute().getInput(); + assertJson(json).isSimilarTo("{" + + "\"repositories\": [" + + " {" + + " \"key\": \"xoo\"," + + " \"name\": \"SonarQube\"," + + " \"language\": \"xoo\"" + + " }," + + " {" + + " \"key\": \"squid\"," + + " \"name\": \"SonarQube\"," + + " \"language\": \"ws\"" + + " }" + + " ]" + + "}"); + } + + @Test + public void response_contains_languages() { + String json = tester.newRequest().execute().getInput(); + + assertJson(json).isSimilarTo("{" + + "\"languages\": {" + + " \"xoo\": \"Xoo\"," + + " \"ws\": \"Whitespace\"" + + " }" + + "}"); + } + + @Test + public void response_contains_quality_profiles_of_default_organization() { + insertQualityProfiles(db.getDefaultOrganization()); + + String json = tester.newRequest().execute().getInput(); + assertJson(json).isSimilarTo("{" + + "\"qualityprofiles\": [" + + " {" + + " \"key\": \"XOO_P1\"," + + " \"name\": \"P1\"," + + " \"lang\": \"xoo\"" + + " }," + + " {" + + " \"key\": \"XOO_P2\"," + + " \"name\": \"P2\"," + + " \"lang\": \"xoo\"," + + " \"parentKey\": \"XOO_P1\"" + + " }" + + " ]" + + "}"); + } + + @Test + public void response_contains_quality_profiles_of_specified_organization() { + OrganizationDto org = db.organizations().insert(); + insertQualityProfiles(org); - Language xoo = mock(Language.class); - when(xoo.getKey()).thenReturn("xoo"); - when(xoo.getName()).thenReturn("Xoo"); - Language whitespace = mock(Language.class); - when(whitespace.getKey()).thenReturn("ws"); - when(whitespace.getName()).thenReturn("Whitespace"); - when(languages.get("xoo")).thenReturn(xoo); - when(languages.all()).thenReturn(new Language[] {xoo, whitespace}); + String json = tester.newRequest() + .setParam("organization", org.getKey()) + .execute().getInput(); + + assertJson(json).isSimilarTo("{" + + "\"qualityprofiles\": [" + + " {" + + " \"key\": \"XOO_P1\"," + + " \"name\": \"P1\"," + + " \"lang\": \"xoo\"" + + " }," + + " {" + + " \"key\": \"XOO_P2\"," + + " \"name\": \"P2\"," + + " \"lang\": \"xoo\"," + + " \"parentKey\": \"XOO_P1\"" + + " }" + + " ]" + + "}"); + } + + @Test + public void throw_NotFoundException_if_organization_does_not_exist() { + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("No organization with key 'does_not_exist'"); + + tester.newRequest() + .setParam("organization", "does_not_exist") + .execute(); + } + @Test + public void canWrite_is_true_if_user_is_profile_administrator_of_default_organization() { + userSession.addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, db.getDefaultOrganization()); + + String json = tester.newRequest().execute().getInput(); + + assertJson(json).isSimilarTo("{ \"canWrite\": true }"); + } + + @Test + public void canWrite_is_true_if_user_is_profile_administrator_of_specified_organization() { + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization); + + String json = tester.newRequest() + .setParam("organization", organization.getKey()) + .execute().getInput(); + + assertJson(json).isSimilarTo("{ \"canWrite\": true }"); + } + + @Test + public void canWrite_is_false_if_user_is_not_profile_administrator_of_specified_organization() { + OrganizationDto organization1 = db.organizations().insert(); + OrganizationDto organization2 = db.organizations().insert(); + userSession.addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization1); + + String json = tester.newRequest() + .setParam("organization", organization2.getKey()) + .execute().getInput(); + + assertJson(json).isSimilarTo("{ \"canWrite\": false }"); + } + + @Test + public void canWrite_is_false_if_user_is_not_profile_administrator_of_default_organization() { + OrganizationDto organization = db.organizations().insert(); + userSession.addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization); + + String json = tester.newRequest().execute().getInput(); + + assertJson(json).isSimilarTo("{ \"canWrite\": false }"); + } + + private void insertRules() { RuleRepositoryDto repo1 = new RuleRepositoryDto("xoo", "xoo", "SonarQube"); RuleRepositoryDto repo2 = new RuleRepositoryDto("squid", "ws", "SonarQube"); db.getDbClient().ruleRepositoryDao().insert(db.getSession(), asList(repo1, repo2)); db.getSession().commit(); - when(i18n.message(isA(Locale.class), anyString(), anyString())).thenAnswer( invocation -> invocation.getArguments()[1]); + } - tester.newGetRequest("api/rules", "app").execute().assertJson(this.getClass(), "app.json"); + private void insertQualityProfiles(OrganizationDto organization) { + QualityProfileDto profile1 = QProfileTesting.newXooP1(organization); + QualityProfileDto profile2 = QProfileTesting.newXooP2(organization).setParentKee(QProfileTesting.XOO_P1_KEY); + db.getDbClient().qualityProfileDao().insert(db.getSession(), profile1); + db.getDbClient().qualityProfileDao().insert(db.getSession(), profile2); + db.commit(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java index 4923ac17ccf..7b40ab3dd42 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/ws/DeleteActionTest.java @@ -23,6 +23,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.rule.RuleKey; +import org.sonar.db.DbClient; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.organization.DefaultOrganizationProvider; @@ -44,10 +45,9 @@ public class DeleteActionTest { private RuleDeleter ruleDeleter = mock(RuleDeleter.class); private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.fromUuid("ORG1"); - private RuleWsSupport ruleWsSupport = new RuleWsSupport(userSession, defaultOrganizationProvider); + private RuleWsSupport ruleWsSupport = new RuleWsSupport(mock(DbClient.class), userSession, defaultOrganizationProvider); private WsTester tester = new WsTester(new RulesWs(new DeleteAction(ruleDeleter, ruleWsSupport))); - @Test public void delete_custom_rule() throws Exception { logInAsQProfileAdministrator(); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/AppActionTest/app.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/AppActionTest/app.json deleted file mode 100644 index 2a380b5d905..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/AppActionTest/app.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "canWrite": true, - "qualityprofiles": [ - { - "key": "XOO_P1", - "name": "P1", - "lang": "xoo" - }, - { - "key": "XOO_P2", - "name": "P2", - "lang": "xoo", - "parentKey": "XOO_P1" - } - ], - "languages": { - "xoo": "Xoo", - "ws": "Whitespace" - }, - "repositories": [ - { - "key": "xoo", - "name": "SonarQube", - "language": "xoo" - }, - { - "key": "squid", - "name": "SonarQube", - "language": "ws" - } - ], - "statuses": { - "BETA": "rules.status.beta", - "DEPRECATED": "rules.status.deprecated", - "READY": "rules.status.ready" - } -} - |