From 14eff68b9c587cf8d1bb8246ce7158bf4ddd9c93 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Beno=C3=AEt=20Gianinetti?= Date: Mon, 4 Feb 2019 17:18:53 +0100 Subject: [PATCH] SONARCLOUD-379 Create POST /api/organizations/set_member_sync --- .../sonar/db/alm/AlmAppInstallDaoTest.java | 2 +- .../java/org/sonar/db/alm/AlmDbTester.java | 3 +- .../organization/OrganizationAlmBinding.java | 2 +- .../organization/ws/AddMemberAction.java | 7 +- .../server/organization/ws/CreateAction.java | 2 +- .../ws/OrganizationsWsModule.java | 3 +- .../ws/OrganizationsWsSupport.java | 13 +- .../organization/ws/RemoveMemberAction.java | 6 +- .../organization/ws/SetMembersSyncAction.java | 92 ++++++++++++ .../organization/ws/AddMemberActionTest.java | 16 +- .../organization/ws/CreateActionTest.java | 6 +- .../ws/OrganizationsWsModuleTest.java | 2 +- .../ws/RemoveMemberActionTest.java | 15 +- .../ws/SetMembersSyncActionTest.java | 142 ++++++++++++++++++ .../organization/ws/UpdateActionTest.java | 6 +- 15 files changed, 299 insertions(+), 18 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/organization/ws/SetMembersSyncAction.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/organization/ws/SetMembersSyncActionTest.java diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmAppInstallDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmAppInstallDaoTest.java index 3a355ced2a4..c07a4c1e8e0 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmAppInstallDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmAppInstallDaoTest.java @@ -155,7 +155,7 @@ public class AlmAppInstallDaoTest { db.getDbClient().almAppInstallDao().insertOrUpdate(db.getSession(), ALM.GITHUB, "the-owner", false, "123456", null); // could be improved, insertOrUpdate should return the DTO with its uuid Optional install = db.getDbClient().almAppInstallDao().selectByOwnerId(db.getSession(), ALM.GITHUB, "the-owner"); - db.getDbClient().organizationAlmBindingDao().insert(db.getSession(), organization, install.get(), "xxx", "xxx"); + db.getDbClient().organizationAlmBindingDao().insert(db.getSession(), organization, install.get(), "xxx", "xxx", true); db.commit(); assertThat(underTest.selectByOrganization(db.getSession(), GITHUB, organization).get().getUuid()).isEqualTo(install.get().getUuid()); diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmDbTester.java index 5b015586bf1..06b0e6f5810 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmDbTester.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/alm/AlmDbTester.java @@ -40,7 +40,7 @@ public class AlmDbTester { public OrganizationAlmBindingDto insertOrganizationAlmBinding(OrganizationDto organization, AlmAppInstallDto almAppInstall) { UserDto user = db.users().insertUser(); - db.getDbClient().organizationAlmBindingDao().insert(db.getSession(), organization, almAppInstall, randomAlphabetic(10), user.getUuid()); + db.getDbClient().organizationAlmBindingDao().insert(db.getSession(), organization, almAppInstall, randomAlphabetic(10), user.getUuid(), true); db.commit(); return db.getDbClient().organizationAlmBindingDao().selectByOrganization(db.getSession(), organization).get(); } @@ -65,5 +65,4 @@ public class AlmDbTester { db.commit(); return db.getDbClient().almAppInstallDao().selectByOwnerId(db.getSession(), dto.getAlm(), dto.getOwnerId()).get(); } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java index ae188f79ca9..452e948eba6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java @@ -26,5 +26,5 @@ import org.sonar.db.organization.OrganizationDto; @ServerSide public interface OrganizationAlmBinding { - void bindOrganization(DbSession dbSession, OrganizationDto organization, String installationId); + void bindOrganization(DbSession dbSession, OrganizationDto organization, String installationId, boolean enableMembersSync); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/AddMemberAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/AddMemberAction.java index 6ac41011099..a4f4ceec277 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/AddMemberAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/AddMemberAction.java @@ -54,13 +54,16 @@ public class AddMemberAction implements OrganizationsWsAction { private final UserIndexer userIndexer; private final DefaultGroupFinder defaultGroupFinder; private final AvatarResolver avatarResolver; + private final OrganizationsWsSupport wsSupport; - public AddMemberAction(DbClient dbClient, UserSession userSession, UserIndexer userIndexer, DefaultGroupFinder defaultGroupFinder, AvatarResolver avatarResolver) { + public AddMemberAction(DbClient dbClient, UserSession userSession, UserIndexer userIndexer, DefaultGroupFinder defaultGroupFinder, + AvatarResolver avatarResolver, OrganizationsWsSupport wsSupport) { this.dbClient = dbClient; this.userSession = userSession; this.userIndexer = userIndexer; this.defaultGroupFinder = defaultGroupFinder; this.avatarResolver = avatarResolver; + this.wsSupport = wsSupport; } @Override @@ -96,6 +99,8 @@ public class AddMemberAction implements OrganizationsWsAction { OrganizationDto organization = checkFoundWithOptional(dbClient.organizationDao().selectByKey(dbSession, organizationKey), "Organization '%s' is not found", organizationKey); UserDto user = checkFound(dbClient.userDao().selectByLogin(dbSession, login), "User '%s' is not found", login); + wsSupport.checkMemberSyncIsDisabled(dbSession, organization); + addMember(dbSession, organization, user); int groups = dbClient.groupMembershipDao().countGroups(dbSession, GroupMembershipQuery.builder() diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java index 52abb4c00ad..06294edf160 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java @@ -156,7 +156,7 @@ public class CreateAction implements OrganizationsWsAction { if (installationId == null) { return; } - organizationAlmBinding.bindOrganization(dbSession, organization, installationId); + organizationAlmBinding.bindOrganization(dbSession, organization, installationId, true); } @CheckForNull 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 4a89e9ec3bd..695466e83e1 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 @@ -50,7 +50,8 @@ public class OrganizationsWsModule extends Module { CreateAction.class, DeleteAction.class, RemoveMemberAction.class, - UpdateAction.class); + UpdateAction.class, + SetMembersSyncAction.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java index 44116152c88..7d3a103079c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java @@ -22,10 +22,13 @@ package org.sonar.server.organization.ws; import javax.annotation.CheckForNull; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.WebService; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.db.organization.OrganizationDto; import org.sonar.server.organization.OrganizationValidation; import org.sonarqube.ws.Organizations.Organization; +import static com.google.common.base.Preconditions.checkArgument; import static java.util.Optional.ofNullable; import static org.sonar.server.organization.OrganizationValidation.DESCRIPTION_MAX_LENGTH; import static org.sonar.server.organization.OrganizationValidation.NAME_MAX_LENGTH; @@ -45,9 +48,11 @@ public class OrganizationsWsSupport { static final String PARAM_LOGIN = "login"; private final OrganizationValidation organizationValidation; + private final DbClient dbClient; - public OrganizationsWsSupport(OrganizationValidation organizationValidation) { + public OrganizationsWsSupport(OrganizationValidation organizationValidation, DbClient dbClient) { this.organizationValidation = organizationValidation; + this.dbClient = dbClient; } String getAndCheckMandatoryName(Request request) { @@ -118,4 +123,10 @@ public class OrganizationsWsSupport { ofNullable(dto.getAvatarUrl()).ifPresent(builder::setAvatar); return builder; } + + + void checkMemberSyncIsDisabled(DbSession dbSession, OrganizationDto organization) { + dbClient.organizationAlmBindingDao().selectByOrganization(dbSession, organization).ifPresent(orgAlmBindingDto -> + checkArgument(!orgAlmBindingDto.isMembersSyncEnable(), "You can't add or remove members when synchronization of organization with alm is enabled.")); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java index 21b66707dd1..02e085860b8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/RemoveMemberAction.java @@ -44,11 +44,13 @@ public class RemoveMemberAction implements OrganizationsWsAction { private final DbClient dbClient; private final UserSession userSession; private final UserIndexer userIndexer; + private final OrganizationsWsSupport wsSupport; - public RemoveMemberAction(DbClient dbClient, UserSession userSession, UserIndexer userIndexer) { + public RemoveMemberAction(DbClient dbClient, UserSession userSession, UserIndexer userIndexer, OrganizationsWsSupport wsSupport) { this.dbClient = dbClient; this.userSession = userSession; this.userIndexer = userIndexer; + this.wsSupport = wsSupport; } @Override @@ -84,7 +86,7 @@ public class RemoveMemberAction implements OrganizationsWsAction { "Organization '%s' is not found", organizationKey); UserDto user = checkFound(dbClient.userDao().selectActiveUserByLogin(dbSession, login), "User '%s' is not found", login); userSession.checkPermission(ADMINISTER, organization); - + wsSupport.checkMemberSyncIsDisabled(dbSession, organization); dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId()) .ifPresent(om -> removeMember(dbSession, organization, user)); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SetMembersSyncAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SetMembersSyncAction.java new file mode 100644 index 00000000000..0c2a45dc0fb --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/SetMembersSyncAction.java @@ -0,0 +1,92 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 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.ws; + +import java.util.Optional; +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.alm.OrganizationAlmBindingDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.user.UserSession; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; +import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_ORGANIZATION; +import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; + +public class SetMembersSyncAction implements OrganizationsWsAction { + + private static final String ENABLED = "enabled"; + private DbClient dbClient; + private UserSession userSession; + + public SetMembersSyncAction(DbClient dbClient, UserSession userSession) { + this.dbClient = dbClient; + this.userSession = userSession; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context.createAction("set_members_sync") + .setDescription("Enable or disable organization members synchronization.
" + + "Requires 'Administer System' permission on the specified organization.") + .setSince("7.7") + .setPost(true) + .setInternal(true) + .setHandler(this); + + action.createParam(PARAM_ORGANIZATION) + .setDescription("Organization key") + .setInternal(true) + .setRequired(true); + + action.createParam(ENABLED) + .setDescription("True to enable members sync, false otherwise.") + .setInternal(true) + .setRequired(true) + .setBooleanPossibleValues(); + } + + @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), + "Organization '%s' does not exist", organizationKey); + + userSession.checkPermission(ADMINISTER, organization); + + Optional orgAlmBindingDto = dbClient.organizationAlmBindingDao().selectByOrganization(dbSession, organization); + checkArgument(orgAlmBindingDto.isPresent(), "Organization '%s' is not bound to an ALM", organization.getKey()); + + dbClient.organizationAlmBindingDao().updateMembersSync(dbSession, orgAlmBindingDto.get(), request.mandatoryParamAsBoolean(ENABLED)); + + dbSession.commit(); + } + + response.noContent(); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/AddMemberActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/AddMemberActionTest.java index 37a52d66dac..659c02040c0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/AddMemberActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/AddMemberActionTest.java @@ -40,6 +40,7 @@ import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.ws.AvatarResolverImpl; +import org.sonar.server.organization.OrganizationValidationImpl; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.index.UserDoc; import org.sonar.server.user.index.UserIndex; @@ -71,9 +72,9 @@ public class AddMemberActionTest { public DbTester db = DbTester.create(); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); - + private OrganizationsWsSupport wsSupport = new OrganizationsWsSupport(new OrganizationValidationImpl(), dbClient); private WsActionTester ws = new WsActionTester( - new AddMemberAction(dbClient, userSession, new UserIndexer(dbClient, es.client()), new DefaultGroupFinder(dbClient), new AvatarResolverImpl())); + new AddMemberAction(dbClient, userSession, new UserIndexer(dbClient, es.client()), new DefaultGroupFinder(dbClient), new AvatarResolverImpl(), wsSupport)); @Test public void add_member_in_db_and_user_index() { @@ -225,6 +226,17 @@ public class AddMemberActionTest { call(organization.getKey(), user.getLogin()); } + @Test + public void fail_if_org_is_bind_to_alm_and_members_sync_is_enabled() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + UserDto user = db.users().insertUser(); + + expectedException.expect(IllegalArgumentException.class); + + call(organization.getKey(), user.getLogin()); + } + @Test public void json_example() { OrganizationDto organization = db.organizations().insert(); 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 afa0a78fc6d..84bd85739c7 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 @@ -115,7 +115,7 @@ public class CreateActionTest { private OrganizationAlmBinding organizationAlmBinding = mock(OrganizationAlmBinding.class); private WsActionTester wsTester = new WsActionTester( - new CreateAction(settings.asConfig(), userSession, dbClient, new OrganizationsWsSupport(organizationValidation), + new CreateAction(settings.asConfig(), userSession, dbClient, new OrganizationsWsSupport(organizationValidation, dbClient), organizationValidation, organizationUpdater, organizationFlags, organizationAlmBinding)); @@ -267,13 +267,13 @@ public class CreateActionTest { .setParam("installationId", "ABCD") .execute(); - verify(organizationAlmBinding).bindOrganization(any(DbSession.class), any(OrganizationDto.class), eq("ABCD")); + verify(organizationAlmBinding).bindOrganization(any(DbSession.class), any(OrganizationDto.class), eq("ABCD"), eq(true)); } @Test public void does_not_bind_organization_when_organizationAlmBinding_is_null() { wsTester = new WsActionTester( - new CreateAction(settings.asConfig(), userSession, dbClient, new OrganizationsWsSupport(organizationValidation), + new CreateAction(settings.asConfig(), userSession, dbClient, new OrganizationsWsSupport(organizationValidation, dbClient), organizationValidation, organizationUpdater, organizationFlags, null)); createUserAndLogInAsSystemAdministrator(); db.qualityGates().insertBuiltInQualityGate(); 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 f1a4db9baf6..89448f24806 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); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/RemoveMemberActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/RemoveMemberActionTest.java index b29f2f0d3f0..b5e01453546 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/RemoveMemberActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/RemoveMemberActionTest.java @@ -46,6 +46,7 @@ import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.OrganizationValidationImpl; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.index.UserIndex; import org.sonar.server.user.index.UserIndexDefinition; @@ -86,8 +87,9 @@ public class RemoveMemberActionTest { private UserIndex userIndex = new UserIndex(es.client(), System2.INSTANCE); private UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); + private OrganizationsWsSupport wsSupport = new OrganizationsWsSupport(new OrganizationValidationImpl(), dbClient); - private WsActionTester ws = new WsActionTester(new RemoveMemberAction(dbClient, userSession, userIndexer)); + private WsActionTester ws = new WsActionTester(new RemoveMemberAction(dbClient, userSession, userIndexer, wsSupport)); private OrganizationDto organization; private ComponentDto project; @@ -334,6 +336,17 @@ public class RemoveMemberActionTest { call(organization.getKey(), user.getLogin()); } + @Test + public void fail_if_org_is_bind_to_alm_and_members_sync_is_enabled() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + UserDto user = db.users().insertUser(); + + expectedException.expect(IllegalArgumentException.class); + + call(organization.getKey(), user.getLogin()); + } + @Test public void remove_org_admin_is_allowed_when_another_org_admin_exists() { OrganizationDto anotherOrganization = db.organizations().insert(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SetMembersSyncActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SetMembersSyncActionTest.java new file mode 100644 index 00000000000..ad6da833c08 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/SetMembersSyncActionTest.java @@ -0,0 +1,142 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 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.ws; + +import java.util.Optional; +import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.server.ws.WebService; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.alm.OrganizationAlmBindingDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.user.UserDto; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; +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 java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.util.Optional.ofNullable; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; +import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_ORGANIZATION; + +public class SetMembersSyncActionTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone().logIn().setRoot(); + @Rule + public DbTester db = DbTester.create(); + + private DbClient dbClient = db.getDbClient(); + + private DbSession dbSession = db.getSession(); + + private WsActionTester ws = new WsActionTester(new SetMembersSyncAction(dbClient, userSession)); + + @Test + public void definition() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + + WebService.Action definition = ws.getDef(); + + assertThat(definition.key()).isEqualTo("set_members_sync"); + assertThat(definition.since()).isEqualTo("7.7"); + assertThat(definition.isPost()).isTrue(); + assertThat(definition.isInternal()).isTrue(); + assertThat(definition.params()) + .extracting(WebService.Param::key, WebService.Param::isRequired) + .containsExactlyInAnyOrder(tuple("organization", true), tuple("enabled", true)); + } + + @Test + public void update_members_sync() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + + sendRequest(organization.getKey(), true); + + Optional dto = dbClient.organizationAlmBindingDao().selectByOrganization(dbSession, organization); + assertThat(dto).isPresent(); + assertThat(dto.get().isMembersSyncEnable()).isTrue(); + } + + @Test + public void returns_no_content() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + + TestResponse result = sendRequest(organization.getKey(), true); + + assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT); + assertThat(result.getInput()).isEmpty(); + } + + @Test + public void fail_if_org_is_not_admin_of_the_org() { + OrganizationDto organization = db.organizations().insert(); + UserDto user = db.users().insertUser(); + userSession.logIn(user); + + expectedException.expect(ForbiddenException.class); + expectedException.expectMessage("Insufficient privileges"); + + sendRequest(organization.getKey(), true); + } + + @Test + public void fail_if_org_is_not_bound_to_an_alm() { + OrganizationDto organization = db.organizations().insert(); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage(String.format("Organization '%s' is not bound to an ALM", organization.getKey())); + + sendRequest(organization.getKey(), true); + } + + @Test + public void fail_if_org_does_not_exist() { + OrganizationDto organization = db.organizations().insert(); + db.alm().insertOrganizationAlmBinding(organization, db.alm().insertAlmAppInstall()); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("Organization '1234' does not exist"); + + sendRequest("1234", true); + } + + private TestResponse sendRequest(@Nullable String organizationKey, @Nullable Boolean enabled) { + TestRequest request = ws.newRequest(); + ofNullable(organizationKey).ifPresent(o -> request.setParam(PARAM_ORGANIZATION, o)); + ofNullable(enabled).ifPresent(e -> request.setParam("enabled", String.valueOf(e))); + + return request.execute(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java index af065de44f9..400d56b5817 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java @@ -25,6 +25,7 @@ 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.exceptions.ForbiddenException; @@ -57,9 +58,12 @@ public class UpdateActionTest { public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public ExpectedException expectedException = ExpectedException.none(); + @Rule + public DbTester db = DbTester.create(); + private DbClient dbClient = db.getDbClient(); private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone().setEnabled(true); - private UpdateAction underTest = new UpdateAction(userSession, new OrganizationsWsSupport(new OrganizationValidationImpl()), dbTester.getDbClient(), organizationFlags); + private UpdateAction underTest = new UpdateAction(userSession, new OrganizationsWsSupport(new OrganizationValidationImpl(), dbClient), dbTester.getDbClient(), organizationFlags); private WsActionTester wsTester = new WsActionTester(underTest); @Test -- 2.39.5