aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-05-04 15:41:31 +0200
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>2015-05-07 14:41:36 +0200
commit7a26b1d96d75751ffebf9d1ea8bbfc3f12d72ca2 (patch)
treedcaa066c9861285c857c142d3cbba47ad7d4c0ac
parent974af974d1dd3b2abec32d4287ed696cedd16a30 (diff)
downloadsonarqube-7a26b1d96d75751ffebf9d1ea8bbfc3f12d72ca2.tar.gz
sonarqube-7a26b1d96d75751ffebf9d1ea8bbfc3f12d72ca2.zip
SONAR-6468 New WS to change a user's password
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java79
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java150
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java14
4 files changed, 242 insertions, 2 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 14edd65aa0a..0fd77b02562 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -759,6 +759,7 @@ class ServerComponents {
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.ChangePasswordAction.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/ChangePasswordAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java
new file mode 100644
index 00000000000..14cbf2edd0a
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/ChangePasswordAction.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.permission.GlobalPermissions;
+import org.sonar.server.user.UpdateUser;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.user.UserUpdater;
+
+public class ChangePasswordAction implements BaseUsersWsAction {
+
+ private static final String PARAM_LOGIN = "login";
+ private static final String PARAM_PASSWORD = "password";
+ private static final String PARAM_PASSWORD_CONFIRMATION = "password_confirmation";
+
+ private final UserUpdater userUpdater;
+
+ public ChangePasswordAction(UserUpdater userUpdater) {
+ this.userUpdater = userUpdater;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("change_password")
+ .setDescription("Update a user's password. Requires Administer System permission.")
+ .setSince("5.2")
+ .setPost(true)
+ .setHandler(this);
+
+ action.createParam(PARAM_LOGIN)
+ .setDescription("User login")
+ .setRequired(true)
+ .setExampleValue("myuser");
+
+ action.createParam(PARAM_PASSWORD)
+ .setDescription("New password")
+ .setRequired(true)
+ .setExampleValue("mypassword");
+
+ action.createParam(PARAM_PASSWORD_CONFIRMATION)
+ .setDescription("Must be the same value as \"password\"")
+ .setRequired(true)
+ .setExampleValue("mypassword");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ UserSession.get().checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+
+ String login = request.mandatoryParam(PARAM_LOGIN);
+ UpdateUser updateUser = UpdateUser.create(login)
+ .setPassword(request.mandatoryParam(PARAM_PASSWORD))
+ .setPasswordConfirmation(request.mandatoryParam(PARAM_PASSWORD_CONFIRMATION));
+
+ userUpdater.update(updateUser);
+ response.noContent();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java
new file mode 100644
index 00000000000..037783c1493
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.sonar.api.config.Settings;
+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.GroupDto;
+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.GroupDao;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.user.db.UserGroupDao;
+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 com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ChangePasswordActionTest {
+
+ static final Settings settings = new Settings().setProperty("sonar.defaultGroup", "sonar-users");
+
+ @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;
+
+ @Before
+ public void setUp() throws Exception {
+ dbTester.truncateTables();
+ esTester.truncateIndices();
+
+ System2 system2 = new System2();
+ UserDao userDao = new UserDao(dbTester.myBatis(), system2);
+ UserGroupDao userGroupDao = new UserGroupDao();
+ GroupDao groupDao = new GroupDao();
+ dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao, userGroupDao, groupDao);
+ session = dbClient.openSession(false);
+ groupDao.insert(session, new GroupDto().setName("sonar-users"));
+ session.commit();
+
+ userIndexer = (UserIndexer) new UserIndexer(dbClient, esTester.client()).setEnabled(true);
+ index = new UserIndex(esTester.client());
+ tester = new WsTester(new UsersWs(new ChangePasswordAction(new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2))));
+ controller = tester.controller("api/users");
+
+ MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ session.close();
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void fail_on_missing_permission() throws Exception {
+ createUser();
+
+ MockUserSession.set().setLogin("polop");
+ tester.newPostRequest("api/users", "change_password")
+ .setParam("login", "john")
+ .execute();
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void fail_on_unknown_user() throws Exception {
+ tester.newPostRequest("api/users", "change_password")
+ .setParam("login", "polop")
+ .setParam("password", "polop")
+ .setParam("password_confirmation", "polop")
+ .execute();
+ }
+
+ @Test
+ public void update_password() throws Exception {
+ createUser();
+ session.clearCache();
+ String originalPassword = dbClient.userDao().selectByLogin(session, "john").getCryptedPassword();
+
+ tester.newPostRequest("api/users", "change_password")
+ .setParam("login", "john")
+ .setParam("password", "Valar Morghulis")
+ .setParam("password_confirmation", "Valar Morghulis")
+ .execute()
+ .assertNoContent();
+
+ session.clearCache();
+ String newPassword = dbClient.userDao().selectByLogin(session, "john").getCryptedPassword();
+ assertThat(newPassword).isNotEqualTo(originalPassword);
+ }
+
+ private void createUser() {
+ dbClient.userDao().insert(session, new UserDto()
+ .setEmail("john@email.com")
+ .setLogin("john")
+ .setName("John")
+ .setScmAccounts(newArrayList("jn"))
+ .setActive(true));
+ session.commit();
+ userIndexer.index();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
index 3ab08ea313e..73d65418c7e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
@@ -42,7 +42,9 @@ public class UsersWsTest {
new CreateAction(mock(UserIndex.class), mock(UserUpdater.class), mock(I18n.class)),
new UpdateAction(mock(UserIndex.class), mock(UserUpdater.class)),
new CurrentUserAction(),
- new DeactivateAction(mock(UserIndex.class), mock(UserUpdater.class))));
+ new DeactivateAction(mock(UserIndex.class), mock(UserUpdater.class)),
+ new ChangePasswordAction(mock(UserUpdater.class)),
+ new CurrentUserAction()));
controller = tester.controller("api/users");
}
@@ -51,7 +53,7 @@ public class UsersWsTest {
assertThat(controller).isNotNull();
assertThat(controller.description()).isNotEmpty();
assertThat(controller.since()).isEqualTo("3.6");
- assertThat(controller.actions()).hasSize(5);
+ assertThat(controller.actions()).hasSize(7);
}
@Test
@@ -81,6 +83,14 @@ public class UsersWsTest {
}
@Test
+ public void define_change_password_action() throws Exception {
+ WebService.Action action = controller.action("change_password");
+ assertThat(action).isNotNull();
+ assertThat(action.isPost()).isTrue();
+ assertThat(action.params()).hasSize(3);
+ }
+
+ @Test
public void define_deactivate_action() throws Exception {
WebService.Action action = controller.action("deactivate");
assertThat(action).isNotNull();