import org.sonar.db.user.UserGroupDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.Message;
-import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.ServerException;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.index.UserIndexer;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Lists.newArrayList;
import static org.sonar.db.user.UserDto.encryptPassword;
+import static org.sonar.server.ws.WsUtils.checkFound;
@ServerSide
public class UserUpdater {
updateUser(dbSession, existingUser);
}
- public void update(UpdateUser updateUser) {
- DbSession dbSession = dbClient.openSession(false);
- try {
- update(dbSession, updateUser);
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
public void update(DbSession dbSession, UpdateUser updateUser) {
UserDto user = dbClient.userDao().selectByLogin(dbSession, updateUser.login());
- if (user == null) {
- throw new NotFoundException(String.format("User with login '%s' has not been found", updateUser.login()));
- }
+ checkFound(user, "User with login '%s' has not been found", updateUser.login());
updateUserDto(dbSession, updateUser, user);
updateUser(dbSession, user);
dbSession.commit();
userIndexer.index();
}
- public void checkCurrentPassword(String login, String password) {
- DbSession dbSession = dbClient.openSession(false);
- try {
- UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, login);
- String cryptedPassword = encryptPassword(password, user.getSalt());
- if (!cryptedPassword.equals(user.getCryptedPassword())) {
- throw new IllegalArgumentException("Incorrect password");
- }
- } finally {
- dbSession.close();
- }
- }
-
private UserDto createNewUserDto(DbSession dbSession, NewUser newUser) {
UserDto userDto = new UserDto();
List<Message> messages = newArrayList();
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
import org.sonar.server.user.UpdateUser;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserUpdater;
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.sonar.db.user.UserDto.encryptPassword;
+
public class ChangePasswordAction implements UsersWsAction {
private static final String PARAM_LOGIN = "login";
private static final String PARAM_PASSWORD = "password";
private static final String PARAM_PREVIOUS_PASSWORD = "previousPassword";
+ private final DbClient dbClient;
private final UserUpdater userUpdater;
private final UserSession userSession;
- public ChangePasswordAction(UserUpdater userUpdater, UserSession userSession) {
+ public ChangePasswordAction(DbClient dbClient, UserUpdater userUpdater, UserSession userSession) {
+ this.dbClient = dbClient;
this.userUpdater = userUpdater;
this.userSession = userSession;
}
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn();
- String login = request.mandatoryParam(PARAM_LOGIN);
- if (login.equals(userSession.getLogin())) {
- String previousPassword = request.mandatoryParam(PARAM_PREVIOUS_PASSWORD);
- userUpdater.checkCurrentPassword(login, previousPassword);
- } else {
- userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
- }
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ String login = request.mandatoryParam(PARAM_LOGIN);
+ if (login.equals(userSession.getLogin())) {
+ String previousPassword = request.mandatoryParam(PARAM_PREVIOUS_PASSWORD);
+ checkCurrentPassword(dbSession, login, previousPassword);
+ } else {
+ userSession.checkPermission(GlobalPermissions.SYSTEM_ADMIN);
+ }
- String password = request.mandatoryParam(PARAM_PASSWORD);
- UpdateUser updateUser = UpdateUser.create(login).setPassword(password);
+ String password = request.mandatoryParam(PARAM_PASSWORD);
+ UpdateUser updateUser = UpdateUser.create(login).setPassword(password);
- userUpdater.update(updateUser);
+ userUpdater.update(dbSession, updateUser);
+ }
response.noContent();
}
+
+ private void checkCurrentPassword(DbSession dbSession, String login, String password) {
+ UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, login);
+ String cryptedPassword = encryptPassword(password, user.getSalt());
+ checkArgument(cryptedPassword.equals(user.getCryptedPassword()), "Incorrect password");
+ }
}
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.user.UserDto;
-import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UpdateUser;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserUpdater;
import org.sonarqube.ws.client.user.UpdateRequest;
import static com.google.common.base.Strings.emptyToNull;
-import static java.lang.String.format;
import static java.util.Collections.singletonList;
+import static org.sonar.server.ws.WsUtils.checkFound;
import static org.sonarqube.ws.client.user.UsersWsParameters.ACTION_UPDATE;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_EMAIL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN;
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN);
UpdateRequest updateRequest = toWsRequest(request);
- doHandle(toWsRequest(request));
- writeResponse(response, updateRequest.getLogin());
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ doHandle(dbSession, toWsRequest(request));
+ writeUser(dbSession, response, updateRequest.getLogin());
+ }
}
- private void doHandle(UpdateRequest request) {
+ private void doHandle(DbSession dbSession, UpdateRequest request) {
String login = request.getLogin();
UpdateUser updateUser = UpdateUser.create(login);
if (request.getName() != null) {
if (!request.getScmAccounts().isEmpty()) {
updateUser.setScmAccounts(request.getScmAccounts());
}
- userUpdater.update(updateUser);
+ userUpdater.update(dbSession, updateUser);
}
- private void writeResponse(Response response, String login) {
+ private void writeUser(DbSession dbSession, Response response, String login) {
JsonWriter json = response.newJsonWriter().beginObject();
- writeUser(json, login);
- json.endObject().close();
- }
-
- private void writeUser(JsonWriter json, String login) {
json.name("user");
Set<String> groups = Sets.newHashSet();
- DbSession dbSession = dbClient.openSession(false);
- try {
- UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
- if (user == null) {
- throw new NotFoundException(format("User '%s' doesn't exist", login));
- }
- groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(login)).get(login));
- userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
- } finally {
- dbClient.closeSession(dbSession);
- }
+ UserDto user = checkFound(dbClient.userDao().selectByLogin(dbSession, login), "User '%s' doesn't exist", login);
+ groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(login)).get(login));
+ userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
+ json.endObject().close();
}
private static UpdateRequest toWsRequest(Request request) {
when(system2.now()).thenReturn(1418215735486L);
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
.setUpdatedAt(PAST));
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@email.com")
.setPassword(null)
.setUpdatedAt(PAST));
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@email.com")
.setPassword(null)
when(system2.now()).thenReturn(1418215735486L);
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2"));
session.commit();
session.clearCache();
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setEmail("marius2@mail.com"));
session.commit();
session.clearCache();
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setScmAccounts(newArrayList("ma2")));
session.commit();
session.clearCache();
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setScmAccounts(newArrayList("ma", "marius33")));
session.commit();
session.clearCache();
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setScmAccounts(null));
session.commit();
session.clearCache();
db.prepareDbUnit(getClass(), "update_user.xml");
createDefaultGroup();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setPassword("password2"));
session.commit();
session.clearCache();
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Password can't be empty");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN).setPassword(null));
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN).setPassword(null));
}
@Test
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Password cannot be changed when external authentication is used");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN).setPassword("password2"));
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN).setPassword("password2"));
}
@Test
createDefaultGroup();
// Existing user, he has no group, and should not be associated to the default one
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
Multimap<String, String> groups = dbClient.groupMembershipDao().selectGroupsByLogins(session, asList(DEFAULT_LOGIN));
assertThat(groups.get(DEFAULT_LOGIN).stream().anyMatch(g -> g.equals("sonar-users"))).isTrue();
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The scm account 'jo' is already used by user(s) : 'John (john)'");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setName("Marius2")
.setEmail("marius2@mail.com")
.setPassword("password2")
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(newArrayList(DEFAULT_LOGIN)));
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(newArrayList(DEFAULT_LOGIN)));
}
@Test
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(newArrayList("marius@lesbronzes.fr")));
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN).setScmAccounts(newArrayList("marius@lesbronzes.fr")));
}
@Test
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("Login and email are automatically considered as SCM accounts");
- underTest.update(UpdateUser.create(DEFAULT_LOGIN)
+ underTest.update(session, UpdateUser.create(DEFAULT_LOGIN)
.setEmail("marius@newmail.com")
.setScmAccounts(newArrayList("marius@newmail.com")));
}
*/
package org.sonar.server.user.ws;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.config.MapSettings;
-import org.sonar.api.config.Settings;
import org.sonar.api.utils.System2;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
-import org.sonar.db.user.GroupDao;
import org.sonar.db.user.GroupTesting;
-import org.sonar.db.user.UserDao;
-import org.sonar.db.user.UserGroupDao;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.ExternalIdentity;
import org.sonar.server.user.NewUser;
import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.SecurityRealmFactory;
import org.sonar.server.user.UserUpdater;
import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class ChangePasswordActionTest {
- private System2 system2 = System2.INSTANCE;
- private Settings settings = new MapSettings();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
@Rule
- public DbTester dbTester = DbTester.create(system2);
+ public DbTester db = DbTester.create();
@Rule
- public EsTester esTester = new EsTester(new UserIndexDefinition(settings));
+ public EsTester esTester = new EsTester(new UserIndexDefinition(new MapSettings()));
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone().logIn("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- private WsTester tester;
- private DbClient dbClient;
- private UserUpdater userUpdater;
- private DbSession session;
- private SecurityRealmFactory realmFactory = mock(SecurityRealmFactory.class);
- private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(dbTester);
+ private UserUpdater userUpdater = new UserUpdater(mock(NewUserNotifier.class), new MapSettings(), db.getDbClient(),
+ new UserIndexer(System2.INSTANCE, db.getDbClient(), esTester.client()), System2.INSTANCE, TestDefaultOrganizationProvider.from(db));
+
+ private WsTester tester = new WsTester(new UsersWs(new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule)));
@Before
public void setUp() {
- System2 system2 = new System2();
- UserDao userDao = new UserDao(dbTester.myBatis(), system2);
- UserGroupDao userGroupDao = new UserGroupDao();
- GroupDao groupDao = new GroupDao(system2);
- dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao, userGroupDao, groupDao);
- session = dbClient.openSession(false);
- groupDao.insert(session, GroupTesting.newGroupDto().setName("sonar-users"));
- session.commit();
-
- UserIndexer userIndexer = new UserIndexer(system2, dbClient, esTester.client());
- userUpdater = new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2, defaultOrganizationProvider);
- tester = new WsTester(new UsersWs(new ChangePasswordAction(userUpdater, userSessionRule)));
- }
-
- @After
- public void tearDown() {
- session.close();
+ db.users().insertGroup(GroupTesting.newGroupDto().setName("sonar-users"));
}
- @Test(expected = ForbiddenException.class)
+ @Test
public void fail_on_missing_permission() throws Exception {
createUser();
-
userSessionRule.logIn("polop");
+
+ expectedException.expect(ForbiddenException.class);
tester.newPostRequest("api/users", "change_password")
.setParam("login", "john")
.execute();
}
- @Test(expected = NotFoundException.class)
+ @Test
public void fail_on_unknown_user() throws Exception {
+ expectedException.expect(NotFoundException.class);
tester.newPostRequest("api/users", "change_password")
.setParam("login", "polop")
.setParam("password", "polop")
@Test
public void update_password() throws Exception {
createUser();
- session.clearCache();
- String originalPassword = dbClient.userDao().selectOrFailByLogin(session, "john").getCryptedPassword();
+ String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
tester.newPostRequest("api/users", "change_password")
.setParam("login", "john")
.execute()
.assertNoContent();
- session.clearCache();
- String newPassword = dbClient.userDao().selectOrFailByLogin(session, "john").getCryptedPassword();
+ String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
assertThat(newPassword).isNotEqualTo(originalPassword);
}
@Test
public void update_password_on_self() throws Exception {
createUser();
- session.clearCache();
- String originalPassword = dbClient.userDao().selectOrFailByLogin(session, "john").getCryptedPassword();
+ String originalPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
userSessionRule.logIn("john");
tester.newPostRequest("api/users", "change_password")
.execute()
.assertNoContent();
- session.clearCache();
- String newPassword = dbClient.userDao().selectOrFailByLogin(session, "john").getCryptedPassword();
+ String newPassword = db.getDbClient().userDao().selectOrFailByLogin(db.getSession(), "john").getCryptedPassword();
assertThat(newPassword).isNotEqualTo(originalPassword);
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void fail_to_update_password_on_self_without_old_password() throws Exception {
createUser();
- session.clearCache();
-
userSessionRule.logIn("john");
+
+ expectedException.expect(IllegalArgumentException.class);
tester.newPostRequest("api/users", "change_password")
.setParam("login", "john")
.setParam("password", "Valar Morghulis")
.execute();
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void fail_to_update_password_on_self_with_bad_old_password() throws Exception {
createUser();
- session.clearCache();
-
userSessionRule.logIn("john");
+
+ expectedException.expect(IllegalArgumentException.class);
tester.newPostRequest("api/users", "change_password")
.setParam("login", "john")
.setParam("previousPassword", "I dunno")
.execute();
}
- @Test(expected = BadRequestException.class)
+ @Test
public void fail_to_update_password_on_external_auth() throws Exception {
userUpdater.create(NewUser.builder()
.setEmail("john@email.com")
.setScmAccounts(newArrayList("jn"))
.setExternalIdentity(new ExternalIdentity("gihhub", "john"))
.build());
- session.clearCache();
- when(realmFactory.hasExternalAuthentication()).thenReturn(true);
+ expectedException.expect(BadRequestException.class);
tester.newPostRequest("api/users", "change_password")
.setParam("login", "john")
.setParam("password", "Valar Morghulis")
new CreateAction(mock(UserUpdater.class), userSessionRule),
new UpdateAction(mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
new CurrentAction(userSessionRule, mock(org.sonar.db.DbClient.class)),
- new ChangePasswordAction(mock(UserUpdater.class), userSessionRule),
+ new ChangePasswordAction(mock(DbClient.class), mock(UserUpdater.class), userSessionRule),
new SearchAction(mock(UserIndex.class), mock(DbClient.class), mock(UserJsonWriter.class))));
controller = tester.controller("api/users");
}