Browse Source

SONAR-8191 last root can't be unset via /api/root/unset_root

tags/6.2-RC1
Sébastien Lesaint 7 years ago
parent
commit
c7c2716387

+ 4
- 0
server/sonar-server/src/main/java/org/sonar/server/root/ws/UnsetRootWsAction.java View File

@@ -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();
}

+ 53
- 19
server/sonar-server/src/test/java/org/sonar/server/root/ws/UnsetRootWsActionTest.java View File

@@ -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();
}

}

+ 4
- 0
sonar-db/src/main/java/org/sonar/db/user/UserDao.java View File

@@ -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;

+ 5
- 1
sonar-db/src/main/java/org/sonar/db/user/UserMapper.java View File

@@ -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);

}

+ 11
- 0
sonar-db/src/main/resources/org/sonar/db/user/UserMapper.xml View File

@@ -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 &lt;&gt; #{login}
</select>

<delete id="removeUserFromGroups" parameterType="long">
DELETE FROM groups_users WHERE user_id=#{id}
</delete>

+ 95
- 0
sonar-db/src/test/java/org/sonar/db/user/UserDaoTest.java View File

@@ -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();

Loading…
Cancel
Save