]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6469 New Java WS to deactivate a user 287/head
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 5 May 2015 11:58:38 +0000 (13:58 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 6 May 2015 09:02:04 +0000 (11:02 +0200)
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/DeactivateAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/user/ws/UsersWs.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/DeactivateActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
server/sonar-server/src/test/resources/org/sonar/server/user/ws/DeactivateActionTest/deactivate_user.json [new file with mode: 0644]

index 9012a2c3f9a578c660aa3e417af8b4e480cd0f1e..ee2eb8f31e23779b07d21478be0dea5f2b2da90b 100644 (file)
  */
 package org.sonar.server.platform;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import javax.annotation.Nullable;
-
+import com.google.common.collect.Lists;
 import org.sonar.api.config.EmailSettings;
 import org.sonar.api.issue.action.Actions;
 import org.sonar.api.platform.ComponentContainer;
@@ -398,7 +392,12 @@ import org.sonar.server.view.index.ViewIndexer;
 import org.sonar.server.ws.ListingWs;
 import org.sonar.server.ws.WebServiceEngine;
 
-import com.google.common.collect.Lists;
+import javax.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
 
 class ServerComponents {
 
@@ -757,6 +756,7 @@ class ServerComponents {
     pico.addSingleton(UsersWs.class);
     pico.addSingleton(org.sonar.server.user.ws.CreateAction.class);
     pico.addSingleton(org.sonar.server.user.ws.UpdateAction.class);
+    pico.addSingleton(org.sonar.server.user.ws.DeactivateAction.class);
     pico.addSingleton(org.sonar.server.user.ws.CurrentUserAction.class);
     pico.addSingleton(org.sonar.server.user.ws.SearchAction.class);
     pico.addSingleton(org.sonar.server.issue.ws.AuthorsAction.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/DeactivateAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/DeactivateAction.java
new file mode 100644 (file)
index 0000000..fc53f38
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.user.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.server.ws.WebService.NewAction;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.user.UserUpdater;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
+
+public class DeactivateAction implements BaseUsersWsAction {
+
+  private static final String PARAM_LOGIN = "login";
+
+  private final UserIndex index;
+  private final UserUpdater userUpdater;
+
+  public DeactivateAction(UserIndex index, UserUpdater userUpdater) {
+    this.index = index;
+    this.userUpdater = userUpdater;
+  }
+
+  @Override
+  public void define(WebService.NewController controller) {
+    NewAction action = controller.createAction("deactivate")
+      .setDescription("Deactivate a user. Requires Administer System permission")
+      .setSince("3.7")
+      .setPost(true)
+      .setHandler(this);
+
+    action.createParam("login")
+      .setDescription("User login")
+      .setRequired(true)
+      .setExampleValue("myuser");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    UserSession.get().checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+    String login = request.mandatoryParam(PARAM_LOGIN);
+    userUpdater.deactivateUserByLogin(login);
+
+    writeResponse(response, login);
+  }
+
+  private void writeResponse(Response response, String login) {
+    UserDoc user = index.getByLogin(login);
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writeUser(json, user);
+    json.endObject().close();
+  }
+
+  private void writeUser(JsonWriter json, UserDoc user) {
+    json.name("user").beginObject()
+      .prop("login", user.login())
+      .prop("name", user.name())
+      .prop("email", user.email())
+      .prop("active", user.active())
+      .name("scmAccounts").beginArray().values(user.scmAccounts()).endArray()
+      .endObject();
+  }
+}
index 492de53a27425a12ef2acfef0c4f0b564ed16aeb..7a96a62140d6ff2e1e1f1b5fa2cdc208453927f2 100644 (file)
@@ -39,7 +39,6 @@ public class UsersWs implements WebService {
       .setDescription("Users management");
 
     defineSearchAction(controller);
-    defineDeactivateAction(controller);
     for (BaseUsersWsAction action : actions) {
       action.define(controller);
     }
@@ -69,20 +68,4 @@ public class UsersWs implements WebService {
 
     RailsHandler.addFormatParam(action);
   }
-
-  private void defineDeactivateAction(NewController controller) {
-    NewAction action = controller.createAction("deactivate")
-      .setDescription("Deactivate a user. Requires Administer System permission")
-      .setSince("3.7")
-      .setPost(true)
-      .setHandler(RailsHandler.INSTANCE);
-
-    action.createParam("login")
-      .setDescription("User login")
-      .setRequired(true)
-      .setExampleValue("myuser");
-
-    RailsHandler.addFormatParam(action);
-  }
-
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/DeactivateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/DeactivateActionTest.java
new file mode 100644 (file)
index 0000000..772e91d
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.user.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.NewUserNotifier;
+import org.sonar.server.user.UserUpdater;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
+import org.sonar.server.user.index.UserIndexDefinition;
+import org.sonar.server.user.index.UserIndexer;
+import org.sonar.server.ws.WsTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+@RunWith(MockitoJUnitRunner.class)
+public class DeactivateActionTest {
+
+  static final Settings settings = new Settings();
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
+
+  @ClassRule
+  public static final EsTester esTester = new EsTester().addDefinitions(new UserIndexDefinition(settings));
+
+  WebService.Controller controller;
+
+  WsTester tester;
+
+  UserIndex index;
+
+  DbClient dbClient;
+
+  UserIndexer userIndexer;
+
+  DbSession session;
+
+  @Mock
+  I18n i18n;
+
+  @Before
+  public void setUp() throws Exception {
+    dbTester.truncateTables();
+    esTester.truncateIndices();
+
+    System2 system2 = new System2();
+    UserDao userDao = new UserDao(dbTester.myBatis(), system2);
+    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao);
+    session = dbClient.openSession(false);
+    session.commit();
+
+    userIndexer = (UserIndexer) new UserIndexer(dbClient, esTester.client()).setEnabled(true);
+    index = new UserIndex(esTester.client());
+    tester = new WsTester(new UsersWs(new DeactivateAction(index,
+      new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2))));
+    controller = tester.controller("api/users");
+
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    session.close();
+  }
+
+  @Test
+  public void deactivate_user() throws Exception {
+    createUser();
+
+    MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    tester.newPostRequest("api/users", "deactivate")
+      .setParam("login", "john")
+      .execute()
+      .assertJson(getClass(), "deactivate_user.json");
+
+    UserDoc user = index.getByLogin("john");
+    assertThat(user.active()).isFalse();
+  }
+
+  @Test(expected = ForbiddenException.class)
+  public void fail_on_missing_permission() throws Exception {
+    createUser();
+
+    MockUserSession.set().setLogin("not_admin");
+    tester.newPostRequest("api/users", "deactivate")
+      .setParam("login", "john").execute();
+  }
+
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unknown_user() throws Exception {
+    MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+    tester.newPostRequest("api/users", "deactivate")
+      .setParam("login", "john").execute();
+  }
+
+  private void createUser() {
+    dbClient.userDao().insert(session, new UserDto()
+      .setActive(true)
+      .setEmail("john@email.com")
+      .setLogin("john")
+      .setName("John")
+      .setScmAccounts("jn"));
+    session.commit();
+    userIndexer.index();
+  }
+
+}
index f7da72560d7b66cf0c1ead77e3eff0b640225cc8..75f3f8ffc2bb2223bbf69ed61610a8bc77f9c393 100644 (file)
@@ -41,7 +41,8 @@ public class UsersWsTest {
     WsTester tester = new WsTester(new UsersWs(
       new CreateAction(mock(UserIndex.class), mock(UserUpdater.class), mock(I18n.class)),
       new UpdateAction(mock(UserIndex.class), mock(UserUpdater.class)),
-      new CurrentUserAction()));
+      new CurrentUserAction(),
+      new DeactivateAction(mock(UserIndex.class), mock(UserUpdater.class))));
     controller = tester.controller("api/users");
   }
 
@@ -84,8 +85,7 @@ public class UsersWsTest {
     WebService.Action action = controller.action("deactivate");
     assertThat(action).isNotNull();
     assertThat(action.isPost()).isTrue();
-    assertThat(action.handler()).isInstanceOf(RailsHandler.class);
-    assertThat(action.params()).hasSize(2);
+    assertThat(action.params()).hasSize(1);
   }
 
   @Test
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/ws/DeactivateActionTest/deactivate_user.json b/server/sonar-server/src/test/resources/org/sonar/server/user/ws/DeactivateActionTest/deactivate_user.json
new file mode 100644 (file)
index 0000000..b532305
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "user": {
+    "login": "john",
+    "name": "John",
+    "email": "john@email.com",
+    "scmAccounts": ["jn"],
+    "active": false
+  }
+}