소스 검색

SONAR-7835 WS permissions/users return permissions in response

tags/6.0-RC1
Teryk Bellahsene 8 년 전
부모
커밋
2990ede97d
21개의 변경된 파일372개의 추가작업 그리고 398개의 파일을 삭제
  1. 2
    3
      it/it-tests/src/test/java/it/authorisation/PermissionSearchTest.java
  2. 1
    14
      server/sonar-server/src/main/java/org/sonar/server/permission/PermissionFinder.java
  3. 4
    1
      server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java
  4. 1
    0
      server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
  5. 67
    35
      server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java
  6. 14
    8
      server/sonar-server/src/main/resources/org/sonar/server/permission/ws/users-example.json
  7. 3
    0
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/OldUsersActionTest.java
  8. 1
    1
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
  9. 6
    7
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/TemplateUsersActionTest.java
  10. 102
    32
      server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java
  11. 12
    8
      server/sonar-server/src/test/resources/org/sonar/server/permission/ws/UsersActionTest/users.json
  12. 8
    12
      sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
  13. 3
    3
      sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java
  14. 1
    1
      sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java
  15. 0
    34
      sonar-db/src/main/java/org/sonar/db/permission/UserRef.java
  16. 4
    0
      sonar-db/src/main/java/org/sonar/db/user/UserDao.java
  17. 22
    21
      sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml
  18. 105
    214
      sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java
  19. 12
    1
      sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java
  20. 1
    1
      sonar-ws/src/main/protobuf/ws-permissions.proto
  21. 3
    2
      sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java

+ 2
- 3
it/it-tests/src/test/java/it/authorisation/PermissionSearchTest.java 파일 보기

@@ -45,7 +45,7 @@ import org.sonarqube.ws.client.permission.RemoveGroupFromTemplateWsRequest;
import org.sonarqube.ws.client.permission.RemoveProjectCreatorFromTemplateWsRequest;
import org.sonarqube.ws.client.permission.RemoveUserFromTemplateWsRequest;
import org.sonarqube.ws.client.permission.SearchTemplatesWsRequest;
import org.sonarqube.ws.client.permission.OldUsersWsRequest;
import org.sonarqube.ws.client.permission.UsersWsRequest;
import util.QaOnly;

import static org.assertj.core.api.Assertions.assertThat;
@@ -106,8 +106,7 @@ public class PermissionSearchTest {
assertThat(searchGlobalPermissionsWsResponse.getPermissionsList().get(0).getGroupsCount()).isEqualTo(2);

WsPermissions.UsersWsResponse users = permissionsWsClient
.users(new OldUsersWsRequest()
.setPermission("admin"));
.users(new UsersWsRequest().setPermission("admin"));
assertThat(users.getUsersList()).extracting("login").contains(LOGIN);

WsPermissions.WsGroupsResponse groupsResponse = permissionsWsClient

+ 1
- 14
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionFinder.java 파일 보기

@@ -35,9 +35,8 @@ import org.sonar.db.component.ResourceDao;
import org.sonar.db.component.ResourceDto;
import org.sonar.db.component.ResourceQuery;
import org.sonar.db.permission.GroupWithPermissionDto;
import org.sonar.db.permission.PermissionDao;
import org.sonar.db.permission.OldPermissionQuery;
import org.sonar.db.permission.UserWithPermissionDto;
import org.sonar.db.permission.PermissionDao;
import org.sonar.server.exceptions.NotFoundException;

import static com.google.common.collect.Lists.newArrayList;
@@ -55,12 +54,6 @@ public class PermissionFinder {
this.permissionDao = dbClient.permissionDao();
}

public List<UserWithPermissionDto> findUsersWithPermission(DbSession dbSession, OldPermissionQuery query) {
Long componentId = componentId(query.component());
int limit = query.pageSize();
return permissionDao.selectUsers(dbSession, query, componentId, offset(query), limit);
}

/**
* Paging for groups search is done in Java in order to correctly handle the 'Anyone' group
*/
@@ -93,12 +86,6 @@ public class PermissionFinder {
return pagedGroups(filteredDtos, paging);
}

private static int offset(OldPermissionQuery query) {
int pageSize = query.pageSize();
int pageIndex = query.pageIndex();
return (pageIndex - 1) * pageSize;
}

private static List<GroupWithPermissionDto> filterMembership(List<GroupWithPermissionDto> dtos, OldPermissionQuery query) {
return newArrayList(Iterables.filter(dtos, new GroupWithPermissionMatchQuery(query)));
}

+ 4
- 1
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequestValidator.java 파일 보기

@@ -48,7 +48,10 @@ public class PermissionRequestValidator {
// static methods only
}

public static void validatePermission(String permission, Optional<WsProjectRef> projectRef) {
public static void validatePermission(@Nullable String permission, Optional<WsProjectRef> projectRef) {
if (permission == null) {
return;
}
if (projectRef.isPresent()) {
validateProjectPermission(permission);
} else {

+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java 파일 보기

@@ -46,6 +46,7 @@ public class PermissionsWsModule extends Module {
RemoveGroupAction.class,
RemoveUserAction.class,
OldUsersAction.class,
UsersAction.class,
GroupsAction.class,
SearchGlobalPermissionsAction.class,
SearchProjectPermissionsAction.class,

+ 67
- 35
server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java 파일 보기

@@ -20,7 +20,11 @@
package org.sonar.server.permission.ws;

import com.google.common.base.Optional;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import com.google.common.collect.TreeMultimap;
import java.util.List;
import java.util.stream.Collectors;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -29,24 +33,25 @@ import org.sonar.api.utils.Paging;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.permission.OldPermissionQuery;
import org.sonar.db.permission.PermissionQuery;
import org.sonar.db.permission.UserWithPermissionDto;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserPermissionDto;
import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.WsPermissions;
import org.sonarqube.ws.WsPermissions.UsersWsResponse;
import org.sonarqube.ws.client.permission.UsersWsRequest;

import static com.google.common.base.Strings.nullToEmpty;
import static org.sonar.api.utils.Paging.forPageIndex;
import static java.util.Collections.emptyList;
import static org.sonar.db.permission.PermissionQuery.DEFAULT_PAGE_SIZE;
import static org.sonar.db.permission.PermissionQuery.RESULTS_MAX_SIZE;
import static org.sonar.db.permission.PermissionQuery.SEARCH_QUERY_MIN_LENGTH;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentDto;
import static org.sonar.server.permission.ws.PermissionRequestValidator.validatePermission;
import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createPermissionParameter;
import static org.sonar.server.permission.ws.PermissionsWsParametersBuilder.createProjectParameters;
import static org.sonar.server.permission.ws.WsProjectRef.newOptionalWsProjectRef;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PERMISSION;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_PROJECT_ID;
@@ -80,7 +85,8 @@ public class UsersAction implements PermissionsWsAction {
.setHandler(this);

action.createParam(Param.TEXT_QUERY)
.setDescription("Limit search to user names that contain the supplied string. Must have at least %d characters.", PermissionQuery.SEARCH_QUERY_MIN_LENGTH)
.setDescription("Limit search to user names that contain the supplied string. Must have at least %d characters.<br/>" +
"When this parameter is not set, only users having at least one permission are returned.", SEARCH_QUERY_MIN_LENGTH)
.setExampleValue("eri");
createPermissionParameter(action).setRequired(false);
createProjectParameters(action);
@@ -99,59 +105,85 @@ public class UsersAction implements PermissionsWsAction {
try {
Optional<ComponentDto> project = dependenciesFinder.searchProject(dbSession, wsProjectRef);
checkProjectAdminUserByComponentDto(userSession, project);
OldPermissionQuery permissionQuery = buildPermissionQuery(request, project);
Long projectIdIfPresent = project.isPresent() ? project.get().getId() : null;
int total = dbClient.permissionDao().countUsers(dbSession, permissionQuery, projectIdIfPresent);
List<UserWithPermissionDto> usersWithPermission = permissionFinder.findUsersWithPermission(dbSession, permissionQuery);
return buildResponse(usersWithPermission, forPageIndex(request.getPage()).withPageSize(request.getPageSize()).andTotal(total));
PermissionQuery dbQuery = buildPermissionQuery(request, project);
List<UserDto> users = findUsers(dbSession, dbQuery);
int total = dbClient.permissionDao().countUsersByQuery(dbSession, dbQuery);
List<UserPermissionDto> userPermissions = findUserPermissions(dbSession, users);
Paging paging = Paging.forPageIndex(request.getPage()).withPageSize(request.getPageSize()).andTotal(total);
return buildResponse(users, userPermissions, paging);
} finally {
dbClient.closeSession(dbSession);
}
}

private static UsersWsRequest toUsersWsRequest(Request request) {
return new UsersWsRequest()
.setPermission(request.mandatoryParam(PARAM_PERMISSION))
UsersWsRequest usersRequest = new UsersWsRequest()
.setPermission(request.param(PARAM_PERMISSION))
.setProjectId(request.param(PARAM_PROJECT_ID))
.setProjectKey(request.param(PARAM_PROJECT_KEY))
.setQuery(request.param(Param.TEXT_QUERY))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));

String searchQuery = usersRequest.getQuery();
checkRequest(searchQuery == null || searchQuery.length() >= SEARCH_QUERY_MIN_LENGTH,
"The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, SEARCH_QUERY_MIN_LENGTH);
return usersRequest;
}

private static UsersWsResponse buildResponse(List<UserWithPermissionDto> usersWithPermission, Paging paging) {
UsersWsResponse.Builder userResponse = UsersWsResponse.newBuilder();
WsPermissions.User.Builder user = WsPermissions.User.newBuilder();
for (UserWithPermissionDto userWithPermission : usersWithPermission) {
userResponse.addUsers(
user
.clear()
.setLogin(userWithPermission.getLogin())
.setName(nullToEmpty(userWithPermission.getName()))
.setEmail(nullToEmpty(userWithPermission.getEmail()))
.setSelected(userWithPermission.getPermission() != null));
}
private static UsersWsResponse buildResponse(List<UserDto> users, List<UserPermissionDto> userPermissions, Paging paging) {
Multimap<Long, String> permissionsByUserId = TreeMultimap.create();
userPermissions.forEach(userPermission -> permissionsByUserId.put(userPermission.getUserId(), userPermission.getPermission()));

UsersWsResponse.Builder response = UsersWsResponse.newBuilder();
users.forEach(user -> {
WsPermissions.User.Builder userResponse = response.addUsersBuilder()
.setLogin(user.getLogin())
.addAllPermissions(permissionsByUserId.get(user.getId()));

userResponse.getPagingBuilder()
.clear()
if (user.getEmail() != null) {
userResponse.setEmail(user.getEmail());
}
if (user.getName() != null) {
userResponse.setName(user.getName());
}
});

response.getPagingBuilder()
.setPageIndex(paging.pageIndex())
.setPageSize(paging.pageSize())
.setTotal(paging.total())
.build();

return userResponse.build();
return response.build();
}

private static OldPermissionQuery buildPermissionQuery(UsersWsRequest request, Optional<ComponentDto> project) {
OldPermissionQuery.Builder permissionQuery = OldPermissionQuery.builder()
.permission(request.getPermission())
.pageIndex(request.getPage())
.pageSize(request.getPageSize())
.search(request.getQuery());
private static PermissionQuery buildPermissionQuery(UsersWsRequest request, Optional<ComponentDto> project) {
PermissionQuery.Builder dbQuery = PermissionQuery.builder()
.setPermission(request.getPermission())
.setPageIndex(request.getPage())
.setPageSize(request.getPageSize())
.setSearchQuery(request.getQuery());
if (project.isPresent()) {
permissionQuery.component(project.get().getKey());
dbQuery.setComponentUuid(project.get().uuid());
}
if (request.getQuery() == null) {
dbQuery.withPermissionOnly();
}

return permissionQuery.build();
return dbQuery.build();
}

private List<UserDto> findUsers(DbSession dbSession, PermissionQuery dbQuery) {
List<String> orderedLogins = dbClient.permissionDao().selectLoginsByPermissionQuery(dbSession, dbQuery);
return Ordering.explicit(orderedLogins).onResultOf(UserDto::getLogin).immutableSortedCopy(dbClient.userDao().selectByLogins(dbSession, orderedLogins));
}

private List<UserPermissionDto> findUserPermissions(DbSession dbSession, List<UserDto> users) {
if (users.isEmpty()) {
return emptyList();
}
List<String> logins = users.stream().map(UserDto::getLogin).collect(Collectors.toList());
return dbClient.permissionDao().selectUserPermissionsByLogins(dbSession, logins);
}
}

+ 14
- 8
server/sonar-server/src/main/resources/org/sonar/server/permission/ws/users-example.json 파일 보기

@@ -1,22 +1,28 @@
{
"paging": {
"pageIndex": 1,
"pageSize": 20,
"total": 2
},
"users": [
{
"login": "admin",
"name": "Administrator",
"email": "admin@admin.com",
"selected": true
"permissions": [
"admin",
"gateadmin",
"profileadmin"
]
},
{
"login": "george.orwell",
"name": "George Orwell",
"email": "george.orwell@1984.net",
"selected": true
"permissions": [
"scan"
]
}
],
"paging": {
"pageSize": 100,
"total": 2,
"pageIndex": 1
}
]
}


+ 3
- 0
server/sonar-server/src/test/java/org/sonar/server/permission/ws/OldUsersActionTest.java 파일 보기

@@ -20,6 +20,7 @@
package org.sonar.server.permission.ws;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -82,6 +83,7 @@ public class OldUsersActionTest {
}

@Test
@Ignore("will be deleted")
public void search_for_users_with_response_example() {
UserDto user1 = insertUser(new UserDto().setLogin("admin").setName("Administrator").setEmail("admin@admin.com"));
UserDto user2 = insertUser(new UserDto().setLogin("george.orwell").setName("George Orwell").setEmail("george.orwell@1984.net"));
@@ -95,6 +97,7 @@ public class OldUsersActionTest {
}

@Test
@Ignore("will be deleted")
public void search_for_users_with_one_permission() {
insertUsers();
String result = ws.newRequest().setParam("permission", "scan").execute().getInput();

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java 파일 보기

@@ -29,6 +29,6 @@ public class PermissionsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new PermissionsWsModule().configure(container);
assertThat(container.size()).isEqualTo(2 + 29);
assertThat(container.size()).isEqualTo(2 + 30);
}
}

+ 6
- 7
server/sonar-server/src/test/java/org/sonar/server/permission/ws/TemplateUsersActionTest.java 파일 보기

@@ -47,8 +47,7 @@ import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usergroups.ws.UserGroupFinder;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.WsPermissions;
import org.sonarqube.ws.WsPermissions.UsersWsResponse;
import org.sonarqube.ws.WsPermissions.OldUsersWsResponse;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.web.UserRole.ADMIN;
@@ -56,7 +55,7 @@ import static org.sonar.db.permission.template.PermissionTemplateTesting.newPerm
import static org.sonar.db.permission.template.PermissionTemplateTesting.newPermissionTemplateUserDto;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonarqube.ws.MediaTypes.PROTOBUF;
import static org.sonarqube.ws.WsPermissions.UsersWsResponse.parseFrom;
import static org.sonarqube.ws.WsPermissions.OldUsersWsResponse.parseFrom;


public class TemplateUsersActionTest {
@@ -124,7 +123,7 @@ public class TemplateUsersActionTest {
.setMediaType(PROTOBUF)
.execute().getInputStream();

UsersWsResponse response = parseFrom(responseStream);
OldUsersWsResponse response = parseFrom(responseStream);

assertThat(response.getUsersList()).extracting("login").containsExactly("login-1", "login-2");
}
@@ -137,7 +136,7 @@ public class TemplateUsersActionTest {
.setMediaType(PROTOBUF)
.execute().getInputStream();

UsersWsResponse response = parseFrom(responseStream);
OldUsersWsResponse response = parseFrom(responseStream);

assertThat(response.getUsersList()).extracting("login").containsOnly("login-1");
}
@@ -150,7 +149,7 @@ public class TemplateUsersActionTest {
.setMediaType(PROTOBUF)
.execute().getInputStream();

WsPermissions.UsersWsResponse response = parseFrom(responseStream);
OldUsersWsResponse response = OldUsersWsResponse.parseFrom(responseStream);

assertThat(response.getUsersList()).extracting("login").containsExactly("login-1", "login-2", "login-3");
assertThat(response.getUsers(2).getSelected()).isFalse();
@@ -166,7 +165,7 @@ public class TemplateUsersActionTest {
.setMediaType(PROTOBUF)
.execute().getInputStream();

WsPermissions.UsersWsResponse response = parseFrom(responseStream);
OldUsersWsResponse response = parseFrom(responseStream);

assertThat(response.getUsersList()).extracting("login").containsOnly("login-2");
}

+ 102
- 32
server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java 파일 보기

@@ -31,8 +31,11 @@ import org.sonar.api.web.UserRole;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ResourceTypesRule;
import org.sonar.db.permission.PermissionDbTester;
import org.sonar.db.user.UserDbTester;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserPermissionDto;
import org.sonar.server.component.ComponentFinder;
@@ -45,7 +48,10 @@ import org.sonar.server.usergroups.ws.UserGroupFinder;
import org.sonar.server.ws.WsActionTester;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.core.permission.GlobalPermissions.QUALITY_GATE_ADMIN;
import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
@@ -65,10 +71,16 @@ public class UsersActionTest {

@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV");
DbClient dbClient = db.getDbClient();
DbSession dbSession = db.getSession();

UserDbTester userDb = new UserDbTester(db);
PermissionDbTester permissionDb = new PermissionDbTester(db);
ComponentDbTester componentDbTester = new ComponentDbTester(db);

WsActionTester ws;
ResourceTypesRule resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT, Qualifiers.VIEW, "DEV");

UsersAction underTest;

@Before
@@ -83,49 +95,108 @@ public class UsersActionTest {

@Test
public void search_for_users_with_response_example() {
UserDto user1 = insertUser(new UserDto().setLogin("admin").setName("Administrator").setEmail("admin@admin.com"));
UserDto user2 = insertUser(new UserDto().setLogin("george.orwell").setName("George Orwell").setEmail("george.orwell@1984.net"));
insertUserRole(new UserPermissionDto().setPermission(SCAN_EXECUTION).setUserId(user1.getId()));
insertUserRole(new UserPermissionDto().setPermission(SCAN_EXECUTION).setUserId(user2.getId()));
dbSession.commit();
UserDto user2 = userDb.insertUser(new UserDto().setLogin("george.orwell").setName("George Orwell").setEmail("george.orwell@1984.net"));
UserDto user1 = userDb.insertUser(new UserDto().setLogin("admin").setName("Administrator").setEmail("admin@admin.com"));
permissionDb.addGlobalPermissionToUser(SCAN_EXECUTION, user2.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user1.getId());
permissionDb.addGlobalPermissionToUser(QUALITY_GATE_ADMIN, user1.getId());
permissionDb.addGlobalPermissionToUser(QUALITY_PROFILE_ADMIN, user1.getId());

String result = ws.newRequest().setParam("permission", "scan").execute().getInput();
String result = ws.newRequest().execute().getInput();

assertJson(result).isSimilarTo(getClass().getResource("users-example.json"));
assertJson(result).withStrictArrayOrder().isSimilarTo(getClass().getResource("users-example.json"));
}

@Test
public void search_for_users_with_one_permission() {
insertUsers();
insertUsersHavingGlobalPermissions();
String result = ws.newRequest().setParam("permission", "scan").execute().getInput();

assertJson(result).isSimilarTo(getClass().getResource("UsersActionTest/users.json"));
assertJson(result).withStrictArrayOrder().isSimilarTo(getClass().getResource("UsersActionTest/users.json"));
}

@Test
public void search_for_users_with_permission_on_project() {
dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key"));
ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid");
UserDto user = insertUser(newUserDto().setLogin("project-user-login").setName("project-user-name"));
userSession.login().addProjectUuidPermissions(SYSTEM_ADMIN, "project-uuid");

// User have permission on project
ComponentDto project = componentDbTester.insertComponent(newProjectDto("project-uuid").setKey("project-key"));
UserDto user = userDb.insertUser(newUserDto());
insertUserRole(new UserPermissionDto().setPermission(ISSUE_ADMIN).setUserId(user.getId()).setComponentId(project.getId()));

// User have permission on another project
ComponentDto anotherProject = componentDbTester.insertComponent(newProjectDto());
UserDto userHavePermissionOnAnotherProject = userDb.insertUser(newUserDto());
insertUserRole(new UserPermissionDto().setPermission(ISSUE_ADMIN).setUserId(userHavePermissionOnAnotherProject.getId()).setComponentId(anotherProject.getId()));

// User has no permission
UserDto withoutPermission = userDb.insertUser(newUserDto());

dbSession.commit();
userSession.login().addProjectUuidPermissions(SYSTEM_ADMIN, "project-uuid");

String result = ws.newRequest()
.setParam(PARAM_PERMISSION, ISSUE_ADMIN)
.setParam(PARAM_PROJECT_ID, "project-uuid")
.execute().getInput();

assertThat(result).contains("project-user-login")
.doesNotContain("login-1");
assertThat(result).contains(user.getLogin())
.doesNotContain(userHavePermissionOnAnotherProject.getLogin())
.doesNotContain(withoutPermission.getLogin());
}

@Test
public void search_only_for_users_with_permission_when_no_search_query() {
userSession.login().setGlobalPermissions(SYSTEM_ADMIN);

// User have permission on project
ComponentDto project = componentDbTester.insertComponent(newProjectDto());
UserDto user = userDb.insertUser(newUserDto());
insertUserRole(new UserPermissionDto().setPermission(ISSUE_ADMIN).setUserId(user.getId()).setComponentId(project.getId()));

// User has no permission
UserDto withoutPermission = userDb.insertUser(newUserDto());

dbSession.commit();

String result = ws.newRequest()
.setParam(PARAM_PROJECT_ID, project.uuid())
.execute().getInput();

assertThat(result).contains(user.getLogin())
.doesNotContain(withoutPermission.getLogin());
}

@Test
public void search_also_for_users_without_permission_when_search_query() {
userSession.login().setGlobalPermissions(SYSTEM_ADMIN);

// User have permission on project
ComponentDto project = componentDbTester.insertComponent(newProjectDto());
UserDto user = userDb.insertUser(newUserDto("with-permission", "with-permission", null));
insertUserRole(new UserPermissionDto().setPermission(ISSUE_ADMIN).setUserId(user.getId()).setComponentId(project.getId()));

// User has no permission
UserDto withoutPermission = userDb.insertUser(newUserDto("without-permission", "without-permission", null));
UserDto anotherUser = userDb.insertUser(newUserDto("another-user", "another-user", null));

dbSession.commit();

String result = ws.newRequest()
.setParam(PARAM_PROJECT_ID, project.uuid())
.setParam(TEXT_QUERY, "with")
.execute().getInput();

assertThat(result).contains(user.getLogin())
.contains(withoutPermission.getLogin())
.doesNotContain(anotherUser.getLogin());
}

@Test
public void search_for_users_with_query_as_a_parameter() {
insertUsers();
insertUsersHavingGlobalPermissions();
String result = ws.newRequest()
.setParam("permission", "scan")
.setParam(Param.TEXT_QUERY, "ame-1")
.setParam(TEXT_QUERY, "ame-1")
.execute().getInput();

assertThat(result).contains("login-1")
@@ -135,10 +206,8 @@ public class UsersActionTest {

@Test
public void search_for_users_with_select_as_a_parameter() {
insertUsers();
insertUsersHavingGlobalPermissions();
String result = ws.newRequest()
.setParam("permission", "scan")
.setParam(Param.SELECTED, SelectionMode.ALL.value())
.execute().getInput();

assertThat(result).contains("login-1", "login-2", "login-3");
@@ -154,13 +223,6 @@ public class UsersActionTest {
.execute();
}

@Test
public void fail_if_permission_parameter_is_not_filled() {
expectedException.expect(IllegalArgumentException.class);

ws.newRequest().execute();
}

@Test
public void fail_if_insufficient_privileges() {
expectedException.expect(ForbiddenException.class);
@@ -195,6 +257,14 @@ public class UsersActionTest {
.execute();
}

@Test
public void fail_if_search_query_is_too_short() {
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The 'q' parameter must have at least 3 characters");

ws.newRequest().setParam(TEXT_QUERY, "ab").execute();
}

private UserDto insertUser(UserDto userDto) {
UserDto user = dbClient.userDao().insert(dbSession, userDto.setActive(true));
dbSession.commit();
@@ -206,13 +276,13 @@ public class UsersActionTest {
dbSession.commit();
}

private void insertUsers() {
UserDto user1 = insertUser(new UserDto().setLogin("login-1").setName("name-1").setEmail("email-1"));
UserDto user2 = insertUser(new UserDto().setLogin("login-2").setName("name-2").setEmail("email-2"));
private void insertUsersHavingGlobalPermissions() {
UserDto user3 = insertUser(new UserDto().setLogin("login-3").setName("name-3").setEmail("email-3"));
UserDto user2 = insertUser(new UserDto().setLogin("login-2").setName("name-2").setEmail("email-2"));
UserDto user1 = insertUser(new UserDto().setLogin("login-1").setName("name-1").setEmail("email-1"));
insertUserRole(new UserPermissionDto().setPermission(SCAN_EXECUTION).setUserId(user1.getId()));
insertUserRole(new UserPermissionDto().setPermission(SCAN_EXECUTION).setUserId(user2.getId()));
insertUserRole(new UserPermissionDto().setPermission(SYSTEM_ADMIN).setUserId(user3.getId()));
insertUserRole(new UserPermissionDto().setPermission(SCAN_EXECUTION).setUserId(user2.getId()));
dbSession.commit();
}
}

+ 12
- 8
server/sonar-server/src/test/resources/org/sonar/server/permission/ws/UsersActionTest/users.json 파일 보기

@@ -1,21 +1,25 @@
{
"paging": {
"pageIndex": 1,
"pageSize": 20,
"total": 2
},
"users": [
{
"login": "login-1",
"name": "name-1",
"email": "email-1",
"selected": true
"permissions": [
"scan"
]
},
{
"login": "login-2",
"name": "name-2",
"email": "email-2",
"selected": true
"permissions": [
"scan"
]
}
],
"paging": {
"pageSize": 100,
"total": 2,
"pageIndex": 1
}
]
}

+ 8
- 12
sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java 파일 보기

@@ -33,7 +33,7 @@ import org.sonar.db.MyBatis;
import org.sonar.db.user.UserPermissionDto;

import static com.google.common.collect.Maps.newHashMap;
import static java.util.Collections.emptyList;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
import static org.sonar.db.DatabaseUtils.executeLargeInputsWithoutOutput;

public class PermissionDao implements Dao {
@@ -50,7 +50,7 @@ public class PermissionDao implements Dao {

/**
* @return a paginated list of users.
* @deprecated use {@link #selectUserPermissionsByQuery(DbSession, PermissionQuery)} instead
* @deprecated
*/
@Deprecated
public List<UserWithPermissionDto> selectUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId, int offset, int limit) {
@@ -60,22 +60,18 @@ public class PermissionDao implements Dao {
}

/**
* Each row returns <code>{@link UserRef}</code>, ordered by user names
* Ordered by user names
*/
public void selectUsersByQuery(DbSession dbSession, PermissionQuery query, ResultHandler handler) {
mapper(dbSession).selectUsersByQuery(query, new RowBounds(query.getPageOffset(), query.getPageSize()), handler);
public List<String> selectLoginsByPermissionQuery(DbSession dbSession, PermissionQuery query) {
return mapper(dbSession).selectLoginsByPermissionQuery(query, new RowBounds(query.getPageOffset(), query.getPageSize()));
}

public int countUsersByQuery(DbSession dbSession, PermissionQuery query) {
return mapper(dbSession).countUsersByQuery(query);
return mapper(dbSession).countUsersByPermissionQuery(query);
}

public List<UserPermissionDto> selectUserPermissionsByQuery(DbSession dbSession, PermissionQuery query) {
if (query.getLogins() != null && query.getLogins().isEmpty()) {
return emptyList();
}

return mapper(dbSession).selectUserPermissionsByQuery(query);
public List<UserPermissionDto> selectUserPermissionsByLogins(DbSession dbSession, List<String> logins) {
return executeLargeInputs(logins, mapper(dbSession)::selectUserPermissionsByLogins);
}

public int countUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId) {

+ 3
- 3
sonar-db/src/main/java/org/sonar/db/permission/PermissionMapper.java 파일 보기

@@ -32,11 +32,11 @@ public interface PermissionMapper {

int countUsers(Map<String, Object> parameters);

void selectUsersByQuery(@Param("query") PermissionQuery query, RowBounds rowBounds, ResultHandler handler);
List<String> selectLoginsByPermissionQuery(@Param("query") PermissionQuery query, RowBounds rowBounds);

int countUsersByQuery(@Param("query") PermissionQuery query);
int countUsersByPermissionQuery(@Param("query") PermissionQuery query);

List<UserPermissionDto> selectUserPermissionsByQuery(@Param("query") PermissionQuery query);
List<UserPermissionDto> selectUserPermissionsByLogins(@Param("logins") List<String> logins);

List<GroupWithPermissionDto> selectGroups(Map<String, Object> parameters);


+ 1
- 1
sonar-db/src/main/java/org/sonar/db/permission/PermissionQuery.java 파일 보기

@@ -166,7 +166,7 @@ public class PermissionQuery {
public PermissionQuery build() {
this.pageIndex = firstNonNull(pageIndex, DEFAULT_PAGE_INDEX);
this.pageSize = firstNonNull(pageSize, DEFAULT_PAGE_SIZE);
checkArgument(searchQuery == null || searchQuery.length() >= 3);
checkArgument(searchQuery == null || searchQuery.length() >= SEARCH_QUERY_MIN_LENGTH);
checkArgument(logins == null || !logins.isEmpty());
return new PermissionQuery(this);
}

+ 0
- 34
sonar-db/src/main/java/org/sonar/db/permission/UserRef.java 파일 보기

@@ -1,34 +0,0 @@
package org.sonar.db.permission;

public class UserRef {
private String login;
private String email;
private String name;

public String getLogin() {
return login;
}

public UserRef setLogin(String login) {
this.login = login;
return this;
}

public String getEmail() {
return email;
}

public UserRef setEmail(String email) {
this.email = email;
return this;
}

public String getName() {
return name;
}

public UserRef setName(String name) {
this.name = name;
return this;
}
}

+ 4
- 0
sonar-db/src/main/java/org/sonar/db/user/UserDao.java 파일 보기

@@ -102,6 +102,10 @@ public class UserDao implements Dao {
return executeLargeInputs(logins, session.getMapper(UserMapper.class)::selectByLogins);
}

/**
* @deprecated since 6.0 please use {@link #selectByLogins(DbSession, Collection)} instead
*/
@Deprecated
public List<UserDto> selectByLogins(Collection<String> logins) {
DbSession session = mybatis.openSession(false);
try {

+ 22
- 21
sonar-db/src/main/resources/org/sonar/db/permission/PermissionMapper.xml 파일 보기

@@ -3,20 +3,17 @@

<mapper namespace="org.sonar.db.permission.PermissionMapper">

<!-- TODO delete when not used anymore -->
<select id="selectUsers" parameterType="map" resultType="UserWithPermission">
SELECT u.login as login, u.name as name, u.email as email, user_role.role as permission
<include refid="usersSelection"/>
ORDER BY u.name
</select>

<!-- TODO delete when not used anymore -->
<select id="countUsers" parameterType="map" resultType="int">
SELECT count(u.login)
<include refid="usersSelection"/>
</select>

<!-- TODO delete when not used anymore -->
<sql id="usersSelection">
FROM users u
LEFT JOIN user_roles user_role ON user_role.user_id=u.id
@@ -45,25 +42,23 @@

<sql id="userColumns">
<!-- lower(u.name) and u.id are present to order by with select distinct -->
u.login as login, u.name as name, u.email as email, lower(u.name), u.id
u.login as login, u.name as name, u.id
</sql>

<select id="selectUsersByQuery" parameterType="map" resultType="org.sonar.db.permission.UserRef">
select distinct <include refid="userColumns" />
<include refid="usersByQuery"/>
<select id="selectLoginsByPermissionQuery" parameterType="map" resultType="string">
select u.login
from (
select distinct <include refid="userColumns" />
<include refid="usersByQuery"/>
) u
order by lower(u.name), u.name, u.id
</select>

<select id="countUsersByQuery" parameterType="map" resultType="int">
<select id="countUsersByPermissionQuery" parameterType="map" resultType="int">
select count(1)
from (
select distinct <include refid="userColumns" />
<include refid="usersByQuery"/>)
</select>

<select id="selectUserPermissionsByQuery" parameterType="map" resultType="UserRole">
select ur.user_id as userId, ur.resource_id as componentId, ur.role as permission
<include refid="usersByQuery" />
<include refid="usersByQuery"/>) u
</select>

<sql id="usersByQuery">
@@ -72,12 +67,6 @@
left join projects p on ur.resource_id = p.id
<where>
and u.active = ${_true}
<if test="query.logins != null">
and u.login in
<foreach collection="query.logins" open="(" close=")" item="login" separator=",">
#{login}
</foreach>
</if>
<if test="query.searchQueryToSql != null">
and lower(u.name) like #{query.searchQueryToSql} ESCAPE '/'
</if>
@@ -88,7 +77,7 @@
and ur.resource_id is null
</if>
<if test="query.componentUuid!=null">
and ur.resource_id is not null
and p.uuid=#{query.componentUuid}
</if>
<if test="query.permission!=null">
and ur.role=#{query.permission}
@@ -97,6 +86,18 @@
</where>
</sql>

<select id="selectUserPermissionsByLogins" parameterType="map" resultType="UserRole">
SELECT ur.user_id AS userId, ur.resource_id AS componentId, ur.role AS permission
FROM user_roles ur
INNER JOIN users u ON u.id = ur.user_id AND u.active = ${_true}
<where>
u.login IN
<foreach collection="logins" open="(" close=")" item="login" separator=",">
#{login}
</foreach>
</where>
</select>

<select id="usersCountByProjectIdAndPermission" parameterType="map"
resultType="org.sonar.db.permission.CountByProjectAndPermissionDto">
SELECT user_role.resource_id as componentId, user_role.role as permission, count(u.login) as count

+ 105
- 214
sonar-db/src/test/java/org/sonar/db/permission/UserWithPermissionDaoTest.java 파일 보기

@@ -19,17 +19,13 @@
*/
package org.sonar.db.permission;

import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
@@ -38,19 +34,20 @@ import org.sonar.db.user.UserDbTester;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserPermissionDto;

import static java.util.Collections.singletonList;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.user.UserTesting.newUserDto;

public class UserWithPermissionDaoTest {

private static final long COMPONENT_ID = 100L;

@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
UserDbTester userDb = new UserDbTester(dbTester);
@@ -61,178 +58,91 @@ public class UserWithPermissionDaoTest {
PermissionDao underTest = new PermissionDao(dbTester.myBatis());

@Test
public void select_all_users_for_project_permission() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");

OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
List<UserWithPermissionDto> result = selectUsers(session, query, COMPONENT_ID);
assertThat(result).hasSize(3);

UserWithPermissionDto user1 = result.get(0);
assertThat(user1.getLogin()).isEqualTo("user1");
assertThat(user1.getName()).isEqualTo("User1");
assertThat(user1.getPermission()).isNotNull();

UserWithPermissionDto user2 = result.get(1);
assertThat(user2.getLogin()).isEqualTo("user2");
assertThat(user2.getName()).isEqualTo("User2");
assertThat(user2.getPermission()).isNotNull();

UserWithPermissionDto user3 = result.get(2);
assertThat(user3.getLogin()).isEqualTo("user3");
assertThat(user3.getName()).isEqualTo("User3");
assertThat(user3.getPermission()).isNull();
}

@Test
public void select_all_users_for_global_permission() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");

OldPermissionQuery query = OldPermissionQuery.builder().permission("admin").build();
List<UserWithPermissionDto> result = selectUsers(session, query, null);
assertThat(result).hasSize(3);

UserWithPermissionDto user1 = result.get(0);
assertThat(user1.getName()).isEqualTo("User1");
assertThat(user1.getPermission()).isNotNull();

UserWithPermissionDto user2 = result.get(1);
assertThat(user2.getName()).isEqualTo("User2");
assertThat(user2.getPermission()).isNull();

UserWithPermissionDto user3 = result.get(2);
assertThat(user3.getName()).isEqualTo("User3");
assertThat(user3.getPermission()).isNull();
}

@Test
public void select_only_user_with_permission() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");

// user1 and user2 have permission user
assertThat(selectUsers(session, OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.IN).build(), COMPONENT_ID)).hasSize(2);
}

@Test
public void select_only_user_without_permission() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
public void select_logins_by_query() {
UserDto user1 = userDb.insertUser(newUserDto());
UserDto user2 = userDb.insertUser(newUserDto());
UserDto user3 = userDb.insertUser(newUserDto());
UserDto user4 = userDb.insertUser(newUserDto());
ComponentDto project = componentDb.insertComponent(newProjectDto());

// Only user3 has not the user permission
assertThat(selectUsers(session, OldPermissionQuery.builder().permission("user").membership(OldPermissionQuery.OUT).build(), COMPONENT_ID)).hasSize(1);
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user1.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user2.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user3.getId());
permissionDb.addGlobalPermissionToUser(PROVISIONING, user3.getId());
permissionDb.addProjectPermissionToUser(USER, user4.getId(), project.getId());

assertThat(selectLoginsByQuery(PermissionQuery.builder().build()))
.containsOnly(user1.getLogin(), user2.getLogin(), user3.getLogin(), user4.getLogin());
assertThat(selectLoginsByQuery(PermissionQuery.builder().setPermission(PROVISIONING).build()))
.containsOnly(user3.getLogin());
assertThat(selectLoginsByQuery(PermissionQuery.builder().withPermissionOnly().setComponentUuid(project.uuid()).build()))
.containsOnly(user4.getLogin());
}

@Test
public void search_by_user_name() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");
public void count_logins_by_query() {
UserDto user1 = userDb.insertUser(newUserDto());
UserDto user2 = userDb.insertUser(newUserDto());
UserDto user3 = userDb.insertUser(newUserDto());
UserDto user4 = userDb.insertUser(newUserDto());
ComponentDto project = componentDb.insertComponent(newProjectDto());

List<UserWithPermissionDto> result = selectUsers(session, OldPermissionQuery.builder().permission("user").search("SEr1").build(), COMPONENT_ID);
assertThat(result).hasSize(1);
assertThat(result.get(0).getName()).isEqualTo("User1");
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user1.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user2.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user3.getId());
permissionDb.addGlobalPermissionToUser(PROVISIONING, user3.getId());
permissionDb.addProjectPermissionToUser(USER, user4.getId(), project.getId());

result = selectUsers(session, OldPermissionQuery.builder().permission("user").search("user").build(), COMPONENT_ID);
assertThat(result).hasSize(3);
assertThat(countUsersByQuery(PermissionQuery.builder().build())).isEqualTo(4);
assertThat(countUsersByQuery(PermissionQuery.builder().setPermission(PROVISIONING).build())).isEqualTo(1);
assertThat(countUsersByQuery(PermissionQuery.builder().withPermissionOnly().setComponentUuid(project.uuid()).build())).isEqualTo(1);
}

@Test
public void select_only_enable_users() {
dbTester.prepareDbUnit(getClass(), "select_only_enable_users.xml");

OldPermissionQuery query = OldPermissionQuery.builder().permission("user").build();
List<UserWithPermissionDto> result = selectUsers(session, query, COMPONENT_ID);
assertThat(result).hasSize(3);

// Disabled user should not be returned
assertThat(Iterables.find(result, input -> input.getLogin().equals("disabledUser"), null)).isNull();
}

@Test
public void select_users() {
UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
UserDto user4 = userDb.insertUser(newUserDto().setName("4-name"));
public void select_logins_by_query_is_ordered_by_name() {
UserDto user3 = userDb.insertUser(newUserDto().setName("3-name").setLogin("3-login"));
UserDto user2 = userDb.insertUser(newUserDto().setName("2-name").setLogin("2-login"));
UserDto user1 = userDb.insertUser(newUserDto().setName("1-name").setLogin("1-login"));
UserDto user4 = userDb.insertUser(newUserDto().setName("4-name").setLogin("4-login"));

ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));

permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user3.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user2.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId());
permissionDb.addProjectPermissionToUser(UserRole.USER, user4.getId(), project.getId());

PermissionQuery.Builder dbQuery = PermissionQuery.builder();
List<UserRef> users = selectUsersByQuery(dbQuery);
int count = countUsersByQuery(dbQuery);
List<UserPermissionDto> permissions = selectUserPermissionsByQuery(dbQuery);

assertThat(users)
.hasSize(4)
.extracting(UserRef::getName)
.containsExactly("1-name", "2-name", "3-name", "4-name");
assertThat(users.get(0)).extracting(UserRef::getEmail, UserRef::getLogin)
.containsExactly(user1.getEmail(), user1.getLogin());
assertThat(count).isEqualTo(4);

assertThat(permissions).hasSize(5).extracting(UserPermissionDto::getUserId, UserPermissionDto::getPermission)
.containsOnlyOnce(
tuple(user1.getId(), GlobalPermissions.SYSTEM_ADMIN),
tuple(user2.getId(), GlobalPermissions.SYSTEM_ADMIN),
tuple(user3.getId(), GlobalPermissions.SYSTEM_ADMIN),
tuple(user3.getId(), GlobalPermissions.PROVISIONING),
tuple(user4.getId(), UserRole.USER));
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user3.getId());
permissionDb.addGlobalPermissionToUser(PROVISIONING, user3.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user2.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user1.getId());
permissionDb.addProjectPermissionToUser(USER, user4.getId(), project.getId());

assertThat(selectLoginsByQuery(PermissionQuery.builder().build())).containsExactly("1-login", "2-login", "3-login", "4-login");
}

@Test
public void select_users_paginated() {
public void select_logins_are_paginated() {
IntStream.rangeClosed(0, 9)
.forEach(i -> userDb.insertUser(newUserDto().setName(i + "-name")));
.forEach(i -> userDb.insertUser(newUserDto().setName(i + "-name").setLogin(i + "-login")));

PermissionQuery.Builder dbQuery = PermissionQuery.builder().setPageIndex(2).setPageSize(3);
List<UserRef> result = selectUsersByQuery(dbQuery);
int count = countUsersByQuery(dbQuery);
List<String> result = selectLoginsByQuery(dbQuery.build());
int count = countUsersByQuery(dbQuery.build());

assertThat(result).hasSize(3).extracting(UserRef::getName)
.containsExactly("3-name", "4-name", "5-name");
assertThat(result).hasSize(3).containsOnlyOnce("3-login", "4-login", "5-login");
assertThat(count).isEqualTo(10);
}

@Test
public void select_users_with_query() {
userDb.insertUser(newUserDto().setName("1-name"));
public void select_logins_with_query() {
userDb.insertUser(newUserDto().setName("1-name").setLogin("1-login"));
userDb.insertUser(newUserDto().setName("unknown"));

PermissionQuery.Builder dbQuery = PermissionQuery.builder().setSearchQuery("nam");
List<UserRef> users = selectUsersByQuery(dbQuery);
int count = countUsersByQuery(dbQuery);
List<String> users = selectLoginsByQuery(dbQuery.build());

assertThat(users).hasSize(1);
assertThat(users.get(0).getName()).isEqualTo("1-name");
assertThat(count).isEqualTo(1);
}

@Test
public void select_user_permissions() {
UserDto user = userDb.insertUser(newUserDto().setLogin("user-login"));
UserDto anotherUser = userDb.insertUser(newUserDto().setLogin("another-login"));
ComponentDto project = componentDb.insertComponent(newProjectDto());
permissionDb.addProjectPermissionToUser(UserRole.ADMIN, user.getId(), project.getId());
permissionDb.addProjectPermissionToUser(UserRole.ADMIN, anotherUser.getId(), project.getId());

PermissionQuery.Builder dbQuery = PermissionQuery.builder()
.setComponentUuid(project.uuid())
.setLogins(singletonList("user-login"))
.withPermissionOnly();
List<UserPermissionDto> result = selectUserPermissionsByQuery(dbQuery);

assertThat(result).hasSize(1);
UserPermissionDto userPermission = result.get(0);
assertThat(userPermission.getComponentId()).isEqualTo(project.getId());
assertThat(userPermission.getPermission()).isEqualTo(UserRole.ADMIN);
assertThat(userPermission.getUserId()).isEqualTo(user.getId());
assertThat(users.get(0)).isEqualTo("1-login");
}

@Test
public void select_users_with_global_permissions() {
public void select_logins_with_global_permissions() {
UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
@@ -240,82 +150,73 @@ public class UserWithPermissionDaoTest {

ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));

permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user3.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user2.getId());
permissionDb.addGlobalPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId());
permissionDb.addGlobalPermissionToUser(SCAN_EXECUTION, user3.getId());
permissionDb.addGlobalPermissionToUser(PROVISIONING, user3.getId());
permissionDb.addGlobalPermissionToUser(SCAN_EXECUTION, user2.getId());
permissionDb.addGlobalPermissionToUser(SYSTEM_ADMIN, user1.getId());
// project permission
permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user4.getId(), project.getId());
permissionDb.addProjectPermissionToUser(SCAN_EXECUTION, user4.getId(), project.getId());

PermissionQuery.Builder dbQuery = PermissionQuery.builder()
.setComponentUuid(null)
.setPermission(GlobalPermissions.SCAN_EXECUTION)
.setPermission(SCAN_EXECUTION)
.withPermissionOnly();
List<UserRef> result = selectUsersByQuery(dbQuery);
int count = countUsersByQuery(dbQuery);
List<String> result = selectLoginsByQuery(dbQuery.build());
int count = countUsersByQuery(dbQuery.build());

assertThat(result).hasSize(2).extracting(UserRef::getName)
.containsExactly("2-name", "3-name");
assertThat(result).hasSize(2).containsExactly(user2.getLogin(), user3.getLogin());
assertThat(count).isEqualTo(2);
}

@Test
public void select_users_with_project_permissions() {
UserDto user3 = userDb.insertUser(newUserDto().setName("3-name"));
UserDto user2 = userDb.insertUser(newUserDto().setName("2-name"));
UserDto user1 = userDb.insertUser(newUserDto().setName("1-name"));
UserDto user4 = userDb.insertUser(newUserDto().setName("4-name"));
public void select_logins_with_project_permissions() {
// create reversed list of user
List<UserDto> dbUsers = IntStream.rangeClosed(1, 4)
.mapToObj(i -> userDb.insertUser(newUserDto().setName(i + "-name").setLogin(i + "-login")))
.collect(Collectors.toList());

ComponentDto project = componentDb.insertComponent(newProjectDto("project-uuid"));

permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user3.getId(), project.getId());
permissionDb.addProjectPermissionToUser(GlobalPermissions.PROVISIONING, user3.getId(), project.getId());
permissionDb.addProjectPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user2.getId(), project.getId());
permissionDb.addProjectPermissionToUser(GlobalPermissions.SYSTEM_ADMIN, user1.getId(), project.getId());
permissionDb.addProjectPermissionToUser(SCAN_EXECUTION, dbUsers.get(0).getId(), project.getId());
permissionDb.addProjectPermissionToUser(PROVISIONING, dbUsers.get(0).getId(), project.getId());
permissionDb.addProjectPermissionToUser(SCAN_EXECUTION, dbUsers.get(1).getId(), project.getId());
permissionDb.addProjectPermissionToUser(SYSTEM_ADMIN, dbUsers.get(2).getId(), project.getId());
// global permission
permissionDb.addGlobalPermissionToUser(GlobalPermissions.SCAN_EXECUTION, user4.getId());
permissionDb.addGlobalPermissionToUser(SCAN_EXECUTION, dbUsers.get(3).getId());

PermissionQuery.Builder dbQuery = PermissionQuery.builder()
.setComponentUuid(null)
.setPermission(GlobalPermissions.SCAN_EXECUTION)
.setPermission(SCAN_EXECUTION)
.withPermissionOnly()
.setComponentUuid(project.uuid());
List<UserRef> result = selectUsersByQuery(dbQuery);
int count = countUsersByQuery(dbQuery);
List<String> result = selectLoginsByQuery(dbQuery.build());
int count = countUsersByQuery(dbQuery.build());

assertThat(result).hasSize(2).extracting(UserRef::getName)
.containsExactly("2-name", "3-name");
assertThat(result).hasSize(2).containsOnlyOnce(dbUsers.get(0).getLogin(), dbUsers.get(1).getLogin());
assertThat(count).isEqualTo(2);
}

@Test
public void should_be_sorted_by_user_name() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions_should_be_sorted_by_user_name.xml");
public void select_user_permissions_by_logins() {
UserDto firstUser = userDb.insertUser(newUserDto());
UserDto secondUser = userDb.insertUser(newUserDto());
UserDto thirdUser = userDb.insertUser(newUserDto());

List<UserWithPermissionDto> result = selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID);
assertThat(result).hasSize(3);
assertThat(result.get(0).getName()).isEqualTo("User1");
assertThat(result.get(1).getName()).isEqualTo("User2");
assertThat(result.get(2).getName()).isEqualTo("User3");
}
ComponentDto project = componentDb.insertComponent(newProjectDto());
permissionDb.addProjectPermissionToUser(ADMIN, firstUser.getId(), project.getId());
permissionDb.addProjectPermissionToUser(USER, secondUser.getId(), project.getId());

@Test
public void should_be_paginated() {
dbTester.prepareDbUnit(getClass(), "users_with_permissions.xml");

List<UserWithPermissionDto> result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 0, 2);
assertThat(result).hasSize(2);
assertThat(result.get(0).getName()).isEqualTo("User1");
assertThat(result.get(1).getName()).isEqualTo("User2");

result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 1, 2);
assertThat(result).hasSize(2);
assertThat(result.get(0).getName()).isEqualTo("User2");
assertThat(result.get(1).getName()).isEqualTo("User3");

result = underTest.selectUsers(session, OldPermissionQuery.builder().permission("user").build(), COMPONENT_ID, 2, 1);
assertThat(result).hasSize(1);
assertThat(result.get(0).getName()).isEqualTo("User3");
ComponentDto anotherProject = componentDb.insertComponent(newProjectDto());
permissionDb.addProjectPermissionToUser(ADMIN, thirdUser.getId(), anotherProject.getId());

List<UserPermissionDto> result = underTest.selectUserPermissionsByLogins(session, (asList(firstUser.getLogin(), secondUser.getLogin(), thirdUser.getLogin())));

assertThat(result)
.extracting(UserPermissionDto::getUserId, UserPermissionDto::getPermission, UserPermissionDto::getComponentId)
.containsOnly(
tuple(firstUser.getId(), ADMIN, project.getId()),
tuple(secondUser.getId(), USER, project.getId()),
tuple(thirdUser.getId(), ADMIN, anotherProject.getId()));
}

@Test
@@ -332,7 +233,7 @@ public class UserWithPermissionDaoTest {
addPermissionToUser(USER, user1.getId(), 456L);

final List<CountByProjectAndPermissionDto> result = new ArrayList<>();
underTest.usersCountByComponentIdAndPermission(dbTester.getSession(), Arrays.asList(123L, 456L, 789L),
underTest.usersCountByComponentIdAndPermission(dbTester.getSession(), asList(123L, 456L, 789L),
context -> result.add((CountByProjectAndPermissionDto) context.getResultObject()));
assertThat(result).hasSize(3);
assertThat(result).extracting("permission").containsOnly(ADMIN, USER);
@@ -340,22 +241,12 @@ public class UserWithPermissionDaoTest {
assertThat(result).extracting("count").containsOnly(3, 1);
}

private List<UserWithPermissionDto> selectUsers(DbSession session, OldPermissionQuery query, @Nullable Long componentId) {
return underTest.selectUsers(session, query, componentId, 0, Integer.MAX_VALUE);
}

private List<UserRef> selectUsersByQuery(PermissionQuery.Builder query) {
List<UserRef> result = new ArrayList<>();
underTest.selectUsersByQuery(session, query.build(), context -> result.add((UserRef) context.getResultObject()));
return result;
}

private int countUsersByQuery(PermissionQuery.Builder query) {
return underTest.countUsersByQuery(session, query.build());
private List<String> selectLoginsByQuery(PermissionQuery query) {
return underTest.selectLoginsByPermissionQuery(session, query);
}

private List<UserPermissionDto> selectUserPermissionsByQuery(PermissionQuery.Builder query) {
return underTest.selectUserPermissionsByQuery(session, query.build());
private int countUsersByQuery(PermissionQuery query) {
return underTest.countUsersByQuery(session, query);
}

private void addPermissionToUser(String permission, long userId, long resourceId) {

+ 12
- 1
sonar-ws/src/main/java/org/sonarqube/ws/client/permission/PermissionsService.java 파일 보기

@@ -21,6 +21,7 @@ package org.sonarqube.ws.client.permission;

import org.sonarqube.ws.WsPermissions;
import org.sonarqube.ws.WsPermissions.CreateTemplateWsResponse;
import org.sonarqube.ws.WsPermissions.OldUsersWsResponse;
import org.sonarqube.ws.WsPermissions.SearchProjectPermissionsWsResponse;
import org.sonarqube.ws.WsPermissions.SearchTemplatesWsResponse;
import org.sonarqube.ws.WsPermissions.UpdateTemplateWsResponse;
@@ -213,7 +214,7 @@ public class PermissionsService extends BaseService {
.setParam(PARAM_PROJECT_KEY_PATTERN, request.getProjectKeyPattern()), UpdateTemplateWsResponse.parser());
}

public UsersWsResponse users(OldUsersWsRequest request) {
public OldUsersWsResponse oldUsers(OldUsersWsRequest request) {
return call(new GetRequest(path("users"))
.setParam(PARAM_PERMISSION, request.getPermission())
.setParam(PARAM_PROJECT_ID, request.getProjectId())
@@ -221,6 +222,16 @@ public class PermissionsService extends BaseService {
.setParam("selected", request.getSelected())
.setParam("p", request.getPage())
.setParam("ps", request.getPageSize())
.setParam("q", request.getQuery()), OldUsersWsResponse.parser());
}

public UsersWsResponse users(UsersWsRequest request) {
return call(new GetRequest(path("users2"))
.setParam(PARAM_PERMISSION, request.getPermission())
.setParam(PARAM_PROJECT_ID, request.getProjectId())
.setParam(PARAM_PROJECT_KEY, request.getProjectKey())
.setParam("p", request.getPage())
.setParam("ps", request.getPageSize())
.setParam("q", request.getQuery()), UsersWsResponse.parser());
}
}

+ 1
- 1
sonar-ws/src/main/protobuf/ws-permissions.proto 파일 보기

@@ -116,7 +116,7 @@ message User {
optional string login = 1;
optional string name = 2;
optional string email = 3;
optional bool selected = 4;
repeated string permissions = 4;
}

message Group {

+ 3
- 2
sonar-ws/src/test/java/org/sonarqube/ws/client/permission/PermissionsServiceTest.java 파일 보기

@@ -22,6 +22,7 @@ package org.sonarqube.ws.client.permission;
import org.junit.Rule;
import org.junit.Test;
import org.sonarqube.ws.WsPermissions;
import org.sonarqube.ws.WsPermissions.OldUsersWsResponse;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.ServiceTester;
@@ -431,7 +432,7 @@ public class PermissionsServiceTest {

@Test
public void users_does_GET_on_Ws_users() {
underTest.users(new OldUsersWsRequest()
underTest.oldUsers(new OldUsersWsRequest()
.setPermission(PERMISSION_VALUE)
.setProjectId(PROJECT_ID_VALUE)
.setProjectKey(PROJECT_KEY_VALUE)
@@ -441,7 +442,7 @@ public class PermissionsServiceTest {
.setQuery(QUERY_VALUE)
);

assertThat(serviceTester.getGetParser()).isSameAs(WsPermissions.UsersWsResponse.parser());
assertThat(serviceTester.getGetParser()).isSameAs(OldUsersWsResponse.parser());
GetRequest getRequest = serviceTester.getGetRequest();
serviceTester.assertThat(getRequest)
.hasPath("users")

Loading…
취소
저장