From 976e8639cf83e476f46d03db90d12763620091cb Mon Sep 17 00:00:00 2001 From: Sébastien Lesaint Date: Thu, 26 Jan 2017 14:06:17 +0100 Subject: SONAR-8676 add ws api/navigation/organization --- .../org/sonar/server/ui/ws/NavigationWsModule.java | 1 + .../org/sonar/server/ui/ws/OrganizationAction.java | 88 +++++++++++ .../sonar/server/ui/ws/organization-example.json | 6 + .../sonar/server/ui/ws/NavigationWsModuleTest.java | 3 +- .../sonar/server/ui/ws/OrganizationActionTest.java | 169 +++++++++++++++++++++ 5 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java create mode 100644 server/sonar-server/src/main/resources/org/sonar/server/ui/ws/organization-example.json create mode 100644 server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java index 304693c72f8..95ddcf36790 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWsModule.java @@ -27,6 +27,7 @@ public class NavigationWsModule extends Module { protected void configureModule() { add( NavigationWs.class, + OrganizationAction.class, ComponentAction.class, GlobalAction.class, SettingsAction.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java new file mode 100644 index 00000000000..eb7c62c6856 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/OrganizationAction.java @@ -0,0 +1,88 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.ui.ws; + +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.web.UserRole; +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 static org.sonar.server.ws.WsUtils.checkFoundWithOptional; + +public class OrganizationAction implements NavigationWsAction { + + private static final String ACTION_NAME = "organization"; + private static final String PARAM_ORGANIZATION = "organization"; + + private final DbClient dbClient; + private final DefaultOrganizationProvider defaultOrganizationProvider; + private final UserSession userSession; + + public OrganizationAction(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider, UserSession userSession) { + this.dbClient = dbClient; + this.defaultOrganizationProvider = defaultOrganizationProvider; + this.userSession = userSession; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction projectNavigation = context.createAction(ACTION_NAME) + .setDescription("Get information concerning organization navigation for the current user") + .setHandler(this) + .setInternal(true) + .setResponseExample(getClass().getResource("organization-example.json")) + .setSince("6.3"); + + projectNavigation.createParam(PARAM_ORGANIZATION) + .setRequired(true) + .setDescription("the organization key") + .setExampleValue("my-org"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + String organizationKey = request.mandatoryParam(PARAM_ORGANIZATION); + try (DbSession dbSession = dbClient.openSession(false)) { + OrganizationDto organization = checkFoundWithOptional( + dbClient.organizationDao().selectByKey(dbSession, organizationKey), + "No organization with key '%s'", organizationKey); + + JsonWriter json = response.newJsonWriter(); + json.beginObject(); + writeOrganization(json, organization); + json.endObject() + .close(); + } + } + + private void writeOrganization(JsonWriter json, OrganizationDto organization) { + json.name("organization") + .beginObject() + .prop("isDefault", organization.getKey().equals(defaultOrganizationProvider.get().getKey())) + .prop("canAdmin", userSession.hasOrganizationPermission(organization.getUuid(), UserRole.ADMIN)) + .endObject(); + } +} diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/organization-example.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/organization-example.json new file mode 100644 index 00000000000..16b45a6dc72 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/organization-example.json @@ -0,0 +1,6 @@ +{ + "organization": { + "isDefault": true, + "canAdmin": true + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java index 214596ac99a..50454fbc338 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/NavigationWsModuleTest.java @@ -24,12 +24,13 @@ import org.junit.Test; import org.sonar.core.platform.ComponentContainer; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER; public class NavigationWsModuleTest { @Test public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new NavigationWsModule().configure(container); - assertThat(container.size()).isEqualTo(4 + 2); + assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java new file mode 100644 index 00000000000..390c5a17ff0 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/OrganizationActionTest.java @@ -0,0 +1,169 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.ui.ws; + +import javax.annotation.Nullable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; +import org.sonar.db.DbTester; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.organization.DefaultOrganizationProvider; +import org.sonar.server.organization.TestDefaultOrganizationProvider; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.TestResponse; +import org.sonar.server.ws.WsActionTester; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.test.JsonAssert.assertJson; + +public class OrganizationActionTest { + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private DbClient dbClient = dbTester.getDbClient(); + private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester); + + private WsActionTester underTest = new WsActionTester(new OrganizationAction(dbClient, defaultOrganizationProvider, userSession)); + + @Test + public void verify_definition() { + WebService.Action def = underTest.getDef(); + + assertThat(def.isInternal()).isTrue(); + assertThat(def.description()).isEqualTo("Get information concerning organization navigation for the current user"); + assertThat(def.since()).isEqualTo("6.3"); + + assertThat(def.params()).hasSize(1); + WebService.Param organization = def.param("organization"); + assertThat(organization.description()).isEqualTo("the organization key"); + assertThat(organization.isRequired()).isTrue(); + assertThat(organization.exampleValue()).isEqualTo("my-org"); + } + + @Test + public void fails_with_IAE_if_parameter_organization_is_not_specified() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'organization' parameter is missing"); + + executeRequest(null); + } + + @Test + public void verify_example() { + + OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); + userSession.login().addOrganizationPermission(defaultOrganization.getUuid(), "admin"); + + TestResponse response = executeRequest(defaultOrganization); + + assertJson(response.getInput()) + .isSimilarTo(underTest.getDef().responseExampleAsString()); + } + + @Test + public void returns_non_admin_and_default_true_when_user_not_logged_in_and_key_is_the_default_organization() { + TestResponse response = executeRequest(dbTester.getDefaultOrganization()); + + verifyResponse(response, true, false); + } + + @Test + public void returns_non_admin_and_default_true_when_user_logged_in_but_not_admin_and_key_is_the_default_organization() { + userSession.login(); + + TestResponse response = executeRequest(dbTester.getDefaultOrganization()); + + verifyResponse(response, true, false); + } + + @Test + public void returns_admin_and_default_true_when_user_logged_in_and_admin_and_key_is_the_default_organization() { + OrganizationDto defaultOrganization = dbTester.getDefaultOrganization(); + userSession.login().addOrganizationPermission(defaultOrganization.getUuid(), "admin"); + + TestResponse response = executeRequest(defaultOrganization); + + verifyResponse(response, true, true); + } + + @Test + public void returns_non_admin_and_default_true_when_user_not_logged_in_and_key_is_not_the_default_organization() { + OrganizationDto organization = dbTester.organizations().insert(); + TestResponse response = executeRequest(organization); + + verifyResponse(response, false, false); + } + + @Test + public void returns_non_admin_and_default_false_when_user_not_logged_in_and_key_is_not_the_default_organization() { + OrganizationDto organization = dbTester.organizations().insert(); + + TestResponse response = executeRequest(organization); + + verifyResponse(response, false, false); + } + + @Test + public void returns_non_admin_and_default_false_when_user_logged_in_but_not_admin_and_key_is_not_the_default_organization() { + OrganizationDto organization = dbTester.organizations().insert(); + userSession.login(); + + TestResponse response = executeRequest(organization); + + verifyResponse(response, false, false); + } + + @Test + public void returns_admin_and_default_false_when_user_logged_in_and_admin_and_key_is_not_the_default_organization() { + OrganizationDto organization = dbTester.organizations().insert(); + userSession.login().addOrganizationPermission(organization.getUuid(), "admin"); + + TestResponse response = executeRequest(organization); + + verifyResponse(response, false, true); + } + + private TestResponse executeRequest(@Nullable OrganizationDto organization) { + TestRequest request = underTest.newRequest(); + if (organization != null) { + request.setParam("organization", organization.getKey()); + } + return request.execute(); + } + + private static void verifyResponse(TestResponse response, boolean isDefault, boolean canAdmin) { + assertJson(response.getInput()) + .isSimilarTo("{" + + " \"organization\": {" + + " \"isDefault\": " + isDefault + "," + + " \"canAdmin\": " + canAdmin + + " }" + + "}"); + } +} -- cgit v1.2.3