@@ -24,6 +24,7 @@ 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.server.exceptions.BadRequestException; | |||
import org.sonar.server.user.UserSession; | |||
public class UnsetRootWsAction implements RootWsAction { | |||
@@ -60,6 +61,9 @@ public class UnsetRootWsAction implements RootWsAction { | |||
String login = request.mandatoryParam(PARAM_LOGIN); | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
if (dbClient.userDao().countRootUsersButLogin(dbSession, login) == 0) { | |||
throw new BadRequestException("Last root can't be unset"); | |||
} | |||
dbClient.userDao().setRoot(dbSession, login, false); | |||
dbSession.commit(); | |||
} |
@@ -29,13 +29,14 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.user.UserDao; | |||
import org.sonar.db.user.UserDto; | |||
import org.sonar.db.user.UserTesting; | |||
import org.sonar.server.exceptions.BadRequestException; | |||
import org.sonar.server.exceptions.ForbiddenException; | |||
import org.sonar.server.tester.UserSessionRule; | |||
import org.sonar.server.ws.TestRequest; | |||
import org.sonar.server.ws.WsActionTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.db.user.UserTesting.newUserDto; | |||
public class UnsetRootWsActionTest { | |||
private static final String SOME_LOGIN = "johndoe"; | |||
@@ -60,7 +61,7 @@ public class UnsetRootWsActionTest { | |||
assertThat(action.isPost()).isTrue(); | |||
assertThat(action.since()).isEqualTo("6.2"); | |||
assertThat(action.description()).isEqualTo("Make the specified user not root.<br/>" + | |||
"Requires to be root."); | |||
"Requires to be root."); | |||
assertThat(action.responseExample()).isNull(); | |||
assertThat(action.deprecatedKey()).isNull(); | |||
assertThat(action.deprecatedSince()).isNull(); | |||
@@ -94,7 +95,7 @@ public class UnsetRootWsActionTest { | |||
@Test | |||
public void execute_fails_with_IAE_when_login_param_is_not_provided() { | |||
userSessionRule.login().setRoot(); | |||
makeAuthenticatedUserRoot(); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("The 'login' parameter is missing"); | |||
@@ -104,13 +105,9 @@ public class UnsetRootWsActionTest { | |||
@Test | |||
public void execute_makes_user_with_specified_login_not_root_when_it_is() { | |||
UserDto otherUser = UserTesting.newUserDto(); | |||
userDao.insert(dbSession, otherUser); | |||
userDao.setRoot(dbSession, otherUser.getLogin(), true); | |||
userDao.insert(dbSession, UserTesting.newUserDto(SOME_LOGIN, "name", "email")); | |||
userDao.setRoot(dbSession, SOME_LOGIN, true); | |||
dbSession.commit(); | |||
userSessionRule.login().setRoot(); | |||
UserDto otherUser = insertRootUser(newUserDto()); | |||
insertRootUser(newUserDto(SOME_LOGIN, "name", "email")); | |||
makeAuthenticatedUserRoot(); | |||
executeRequest(SOME_LOGIN); | |||
@@ -120,13 +117,9 @@ public class UnsetRootWsActionTest { | |||
@Test | |||
public void execute_has_no_effect_when_user_is_already_not_root() { | |||
UserDto otherUser = UserTesting.newUserDto(); | |||
userDao.insert(dbSession, otherUser); | |||
userDao.setRoot(dbSession, otherUser.getLogin(), true); | |||
userDao.insert(dbSession, UserTesting.newUserDto(SOME_LOGIN, "name", "email")); | |||
userDao.setRoot(dbSession, SOME_LOGIN, true); | |||
dbSession.commit(); | |||
userSessionRule.login().setRoot(); | |||
UserDto otherUser = insertRootUser(newUserDto()); | |||
insertNonRootUser(newUserDto(SOME_LOGIN, "name", "email")); | |||
makeAuthenticatedUserRoot(); | |||
executeRequest(SOME_LOGIN); | |||
@@ -134,6 +127,47 @@ public class UnsetRootWsActionTest { | |||
assertThat(userDao.selectByLogin(dbSession, otherUser.getLogin()).isRoot()).isTrue(); | |||
} | |||
@Test | |||
public void execute_fails_with_BadRequestException_when_attempting_to_unset_root_on_last_root_user() { | |||
insertRootUser(newUserDto(SOME_LOGIN, "name", "email")); | |||
insertNonRootUser(newUserDto()); | |||
makeAuthenticatedUserRoot(); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage("Last root can't be unset"); | |||
executeRequest(SOME_LOGIN); | |||
} | |||
@Test | |||
public void execute_fails_with_BadRequestException_when_attempting_to_unset_non_root_and_there_is_no_root_at_all() { | |||
insertNonRootUser(newUserDto(SOME_LOGIN, "name", "email")); | |||
insertNonRootUser(newUserDto()); | |||
makeAuthenticatedUserRoot(); | |||
expectedException.expect(BadRequestException.class); | |||
expectedException.expectMessage("Last root can't be unset"); | |||
executeRequest("non_existing_user"); | |||
} | |||
private UserDto insertNonRootUser(UserDto dto) { | |||
userDao.insert(dbSession, dto); | |||
dbSession.commit(); | |||
return dto; | |||
} | |||
private UserDto insertRootUser(UserDto dto) { | |||
insertNonRootUser(dto); | |||
userDao.setRoot(dbSession, dto.getLogin(), true); | |||
dbSession.commit(); | |||
return dto; | |||
} | |||
private void makeAuthenticatedUserRoot() { | |||
userSessionRule.login().setRoot(); | |||
} | |||
private void expectInsufficientPrivilegesForbiddenException() { | |||
expectedException.expect(ForbiddenException.class); | |||
expectedException.expectMessage("Insufficient privileges"); | |||
@@ -145,8 +179,8 @@ public class UnsetRootWsActionTest { | |||
request.setParam("login", login); | |||
} | |||
return request | |||
.execute() | |||
.getStatus(); | |||
.execute() | |||
.getStatus(); | |||
} | |||
} |
@@ -140,6 +140,10 @@ public class UserDao implements Dao { | |||
return mapper.selectUsers(query); | |||
} | |||
public long countRootUsersButLogin(DbSession dbSession, String login) { | |||
return getMapper(dbSession).countRootUsersButLogin(login); | |||
} | |||
public UserDto insert(DbSession session, UserDto dto) { | |||
getMapper(session).insert(dto); | |||
return dto; |
@@ -53,6 +53,11 @@ public interface UserMapper { | |||
long countByEmail(String email); | |||
/** | |||
* Count actives users which are root and which login is not the specified one. | |||
*/ | |||
long countRootUsersButLogin(@Param("login") String login); | |||
void insert(UserDto userDto); | |||
void update(UserDto userDto); | |||
@@ -80,5 +85,4 @@ public interface UserMapper { | |||
void deletePropertiesMatchingLogin(@Param("propertyKeys") List<String> propertyKeys, @Param("login") String login); | |||
void deactivateUser(@Param("id") long userId, @Param("now") long now); | |||
} |
@@ -98,6 +98,17 @@ | |||
where lower(u.email)=#{email} AND u.active=${_true} | |||
</select> | |||
<select id="countRootUsersButLogin" parameterType="String" resultType="long"> | |||
select | |||
count(1) | |||
from | |||
users u | |||
where | |||
u.active = ${_true} | |||
and u.is_root = ${_true} | |||
and u.login <> #{login} | |||
</select> | |||
<delete id="removeUserFromGroups" parameterType="long"> | |||
DELETE FROM groups_users WHERE user_id=#{id} | |||
</delete> |
@@ -192,6 +192,101 @@ public class UserDaoTest { | |||
assertThat(users).isEmpty(); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_0_when_there_is_no_user_at_all() { | |||
assertThat(underTest.countRootUsersButLogin(session, "bla")).isEqualTo(0); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_0_when_there_is_no_root() { | |||
underTest.insert(session, newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, "bla")).isEqualTo(0); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_0_when_there_is_no_active_root() { | |||
insertNonRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, "bla")).isEqualTo(0); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_count_of_all_active_roots_when_there_specified_login_does_not_exist() { | |||
insertRootUser(newUserDto()); | |||
insertNonRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, "bla")).isEqualTo(3); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_count_of_all_active_roots_when_specified_login_is_not_root() { | |||
insertRootUser(newUserDto()); | |||
String login = insertNonRootUser(newUserDto()).getLogin(); | |||
insertRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, login)).isEqualTo(3); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_count_of_all_active_roots_when_specified_login_is_inactive_root() { | |||
insertRootUser(newUserDto()); | |||
insertNonRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
String inactiveRootLogin = insertInactiveRootUser(newUserDto()).getLogin(); | |||
insertInactiveRootUser(newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, inactiveRootLogin)).isEqualTo(3); | |||
} | |||
@Test | |||
public void countRootUsersButLogin_returns_count_of_all_active_roots_minus_one_when_specified_login_is_active_root() { | |||
insertRootUser(newUserDto()); | |||
insertNonRootUser(newUserDto()); | |||
insertRootUser(newUserDto()); | |||
String rootLogin = insertRootUser(newUserDto()).getLogin(); | |||
insertInactiveRootUser(newUserDto()); | |||
insertInactiveRootUser(newUserDto()); | |||
session.commit(); | |||
assertThat(underTest.countRootUsersButLogin(session, rootLogin)).isEqualTo(2); | |||
} | |||
private UserDto insertInactiveRootUser(UserDto dto) { | |||
insertRootUser(dto); | |||
dto.setActive(false); | |||
underTest.update(session, dto); | |||
session.commit(); | |||
return dto; | |||
} | |||
private UserDto insertRootUser(UserDto dto) { | |||
underTest.insert(session, dto); | |||
underTest.setRoot(session, dto.getLogin(), true); | |||
session.commit(); | |||
return dto; | |||
} | |||
private UserDto insertNonRootUser(UserDto dto) { | |||
underTest.insert(session, dto); | |||
session.commit(); | |||
return dto; | |||
} | |||
@Test | |||
public void insert_user() { | |||
Long date = DateUtils.parseDate("2014-06-20").getTime(); |