aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2017-03-17 17:14:45 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2017-03-21 13:05:50 +0100
commit5acc864451b7a727c55697093fbf0439af6994bf (patch)
tree4a63fa16ae21c5a73dd181e5fcc1ec1f4fd435fc
parent14cbaf7f117d8e6fac992459a4e32089b1a81fbe (diff)
downloadsonarqube-5acc864451b7a727c55697093fbf0439af6994bf.tar.gz
sonarqube-5acc864451b7a727c55697093fbf0439af6994bf.zip
SONAR-8968 Add organization parameter in api/users/groups
-rw-r--r--it/it-tests/src/test/java/it/organization/OrganizationTest.java6
-rw-r--r--it/it-tests/src/test/java/util/user/UserRule.java3
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipDao.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipQuery.java19
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml1
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java52
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java49
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java43
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java136
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/user/GroupsRequest.java13
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersService.java2
-rw-r--r--sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersWsParameters.java1
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/user/GroupsRequestTest.java11
-rw-r--r--sonar-ws/src/test/java/org/sonarqube/ws/client/user/UsersServiceTest.java3
15 files changed, 252 insertions, 93 deletions
diff --git a/it/it-tests/src/test/java/it/organization/OrganizationTest.java b/it/it-tests/src/test/java/it/organization/OrganizationTest.java
index dcde71a0995..cf1783c879c 100644
--- a/it/it-tests/src/test/java/it/organization/OrganizationTest.java
+++ b/it/it-tests/src/test/java/it/organization/OrganizationTest.java
@@ -312,7 +312,7 @@ public class OrganizationTest {
}
@Test
- public void deleting_an_organization_also_deletes_group_permissions_and_projects_and_check_security() {
+ public void deleting_an_organization_also_deletes_projects_and_check_security() {
verifyNoExtraOrganization();
String orgKeyAndName = "org-key";
@@ -343,10 +343,6 @@ public class OrganizationTest {
adminOrganizationService.delete(orgKeyAndName);
expect404HttpError(() -> searchSampleProject(orgKeyAndName, componentsService));
- assertThat(groupManagement.getUserGroups("bob").getGroups())
- .extracting(Groups.Group::getName)
- .doesNotContain("grp1", "grp2");
-
verifyNoExtraOrganization();
}
diff --git a/it/it-tests/src/test/java/util/user/UserRule.java b/it/it-tests/src/test/java/util/user/UserRule.java
index 51dc8b95683..038e0f150eb 100644
--- a/it/it-tests/src/test/java/util/user/UserRule.java
+++ b/it/it-tests/src/test/java/util/user/UserRule.java
@@ -218,8 +218,7 @@ public class UserRule extends ExternalResource implements GroupManagement {
.setParam("login", userLogin)
.setParam("selected", "selected");
addOrganizationParam(request);
- WsResponse response = adminWsClient().wsConnector().call(request);
- assertThat(response.code()).isEqualTo(200);
+ WsResponse response = adminWsClient().wsConnector().call(request).failIfNotSuccessful();
return Groups.parse(response.content());
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipDao.java
index 4c30022d770..e3077809c0f 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipDao.java
@@ -36,12 +36,12 @@ import static org.sonar.db.DatabaseUtils.executeLargeInputs;
public class GroupMembershipDao implements Dao {
public List<GroupMembershipDto> selectGroups(DbSession session, GroupMembershipQuery query, Integer userId, int offset, int limit) {
- Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId);
+ Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId, "organizationUuid", query.organizationUuid());
return mapper(session).selectGroups(params, new RowBounds(offset, limit));
}
public int countGroups(DbSession session, GroupMembershipQuery query, Integer userId) {
- Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId);
+ Map<String, Object> params = ImmutableMap.of("query", query, "userId", userId, "organizationUuid", query.organizationUuid());
return mapper(session).countGroups(params);
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipQuery.java
index 165a3bc52f1..6b1dee75f06 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipQuery.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupMembershipQuery.java
@@ -27,6 +27,7 @@ import org.apache.commons.lang.StringUtils;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
public class GroupMembershipQuery {
@@ -38,6 +39,7 @@ public class GroupMembershipQuery {
public static final String OUT = "OUT";
public static final Set<String> AVAILABLE_MEMBERSHIP = ImmutableSet.of(ANY, IN, OUT);
+ private final String organizationUuid;
private final String membership;
private final String groupSearch;
@@ -51,9 +53,10 @@ public class GroupMembershipQuery {
// index of selected page. Start with 1.
private final int pageIndex;
- private GroupMembershipQuery(Builder builder) {
+ private GroupMembershipQuery(Builder builder, String organizationUuid) {
this.membership = builder.membership;
this.groupSearch = builder.groupSearch;
+ this.organizationUuid = organizationUuid;
this.groupSearchSql = groupSearchToSql(groupSearch);
this.pageSize = builder.pageSize;
@@ -70,6 +73,10 @@ public class GroupMembershipQuery {
return sql;
}
+ public String organizationUuid() {
+ return organizationUuid;
+ }
+
@CheckForNull
public String membership() {
return membership;
@@ -96,15 +103,22 @@ public class GroupMembershipQuery {
}
public static class Builder {
+ private String organizationUuid;
private String membership;
private String groupSearch;
private Integer pageIndex = DEFAULT_PAGE_INDEX;
+
private Integer pageSize = DEFAULT_PAGE_SIZE;
private Builder() {
}
+ public Builder organizationUuid(String organizationUuid) {
+ this.organizationUuid = organizationUuid;
+ return this;
+ }
+
public Builder membership(@Nullable String membership) {
this.membership = membership;
return this;
@@ -141,10 +155,11 @@ public class GroupMembershipQuery {
}
public GroupMembershipQuery build() {
+ checkNotNull(organizationUuid, "Organization uuid cant be null");
initMembership();
initPageIndex();
initPageSize();
- return new GroupMembershipQuery(this);
+ return new GroupMembershipQuery(this, organizationUuid);
}
}
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml
index 57bbdba073c..a24001488b7 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml
@@ -7,6 +7,7 @@
FROM groups g
LEFT JOIN groups_users gu ON gu.group_id=g.id AND gu.user_id=#{userId}
<where>
+ AND g.organization_uuid=#{organizationUuid}
<choose>
<when test="query.membership() == 'IN'">
AND gu.user_id IS NOT NULL
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java
index 1fcb01f82c8..4585ef0a145 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java
@@ -71,17 +71,27 @@ public class GroupMembershipDaoTest {
db.users().insertMember(group2, user2);
// user1 is member of 3 groups
- assertThat(underTest.countGroups(db.getSession(), builder().membership(IN).build(), user1.getId())).isEqualTo(3);
- assertThat(underTest.countGroups(db.getSession(), builder().membership(OUT).build(), user1.getId())).isZero();
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user1.getId())).isEqualTo(3);
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user1.getId())).isZero();
// user2 is member of 1 group on 3
- assertThat(underTest.countGroups(db.getSession(), builder().membership(IN).build(), user2.getId())).isEqualTo(1);
- assertThat(underTest.countGroups(db.getSession(), builder().membership(OUT).build(), user2.getId())).isEqualTo(2);
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user2.getId())).isEqualTo(1);
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user2.getId())).isEqualTo(2);
// user3 is member of 0 group
- assertThat(underTest.countGroups(db.getSession(), builder().membership(IN).build(), user3.getId())).isZero();
- assertThat(underTest.countGroups(db.getSession(), builder().membership(OUT).build(), user3.getId())).isEqualTo(3);
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user3.getId())).isZero();
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user3.getId())).isEqualTo(3);
// unknown user is member of 0 group
- assertThat(underTest.countGroups(db.getSession(), builder().membership(IN).build(), 999)).isZero();
- assertThat(underTest.countGroups(db.getSession(), builder().membership(OUT).build(), 999)).isEqualTo(3);
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), 999)).isZero();
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), 999)).isEqualTo(3);
+ }
+
+ @Test
+ public void count_groups_only_from_given_organization() throws Exception {
+ OrganizationDto otherOrganization = db.organizations().insert();
+ GroupDto otherGroup = db.users().insertGroup(otherOrganization, "sonar-administrators-other_orga");
+ db.users().insertMember(group1, user1);
+ db.users().insertMember(otherGroup, user1);
+
+ assertThat(underTest.countGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user1.getId())).isEqualTo(1);
}
@Test
@@ -92,17 +102,27 @@ public class GroupMembershipDaoTest {
db.users().insertMember(group2, user2);
// user1 is member of 3 groups
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(IN).build(), user1.getId(), 0, 10)).hasSize(3);
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(OUT).build(), user1.getId(), 0, 10)).isEmpty();
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user1.getId(), 0, 10)).hasSize(3);
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user1.getId(), 0, 10)).isEmpty();
// user2 is member of 1 group on 3
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(IN).build(), user2.getId(), 0, 10)).hasSize(1);
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(OUT).build(), user2.getId(), 0, 10)).hasSize(2);
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user2.getId(), 0, 10)).hasSize(1);
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user2.getId(), 0, 10)).hasSize(2);
// user3 is member of 0 group
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(IN).build(), user3.getId(), 0, 10)).isEmpty();
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(OUT).build(), user3.getId(), 0, 10)).hasSize(3);
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user3.getId(), 0, 10)).isEmpty();
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), user3.getId(), 0, 10)).hasSize(3);
// unknown user is member of 0 group
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(IN).build(), 999, 0, 10)).isEmpty();
- assertThat(underTest.selectGroups(db.getSession(), builder().membership(OUT).build(), 999, 0, 10)).hasSize(3);
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), 999, 0, 10)).isEmpty();
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(OUT).build(), 999, 0, 10)).hasSize(3);
+ }
+
+ @Test
+ public void select_groups_only_from_given_organization() {
+ OrganizationDto otherOrganization = db.organizations().insert();
+ GroupDto otherGroup = db.users().insertGroup(otherOrganization, "sonar-administrators-other_orga");
+ db.users().insertMember(group1, user1);
+ db.users().insertMember(otherGroup, user1);
+
+ assertThat(underTest.selectGroups(db.getSession(), builder().organizationUuid(organizationDto.getUuid()).membership(IN).build(), user1.getId(), 0, 10)).hasSize(1);
}
@Test
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java
index efab0b1935b..34fb8d5adc0 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupMembershipQueryTest.java
@@ -19,24 +19,53 @@
*/
package org.sonar.db.user;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
public class GroupMembershipQueryTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void create_query() throws Exception {
+ GroupMembershipQuery underTest = GroupMembershipQuery.builder()
+ .groupSearch("sonar-users")
+ .membership(GroupMembershipQuery.IN)
+ .pageIndex(2)
+ .pageSize(10)
+ .organizationUuid("organization_uuid")
+ .build();
+
+ assertThat(underTest.groupSearch()).isEqualTo("sonar-users");
+ assertThat(underTest.membership()).isEqualTo("IN");
+ assertThat(underTest.pageIndex()).isEqualTo(2);
+ assertThat(underTest.pageSize()).isEqualTo(10);
+ assertThat(underTest.organizationUuid()).isEqualTo("organization_uuid");
+ }
+
+ @Test
+ public void fail_on_null_organization() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("Organization uuid cant be null");
+
+ GroupMembershipQuery.builder()
+ .organizationUuid(null)
+ .build();
+ }
+
@Test
public void fail_on_invalid_membership() {
- GroupMembershipQuery.Builder builder = GroupMembershipQuery.builder();
- builder.membership("unknwown");
-
- try {
- builder.build();
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]");
- }
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("Membership is not valid (got unknwown). Availables values are [ANY, IN, OUT]");
+
+ GroupMembershipQuery.builder()
+ .organizationUuid("organization_uuid")
+ .membership("unknwown")
+ .build();
}
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
index f3489463912..c3fee7a2912 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/user/UserDaoTest.java
@@ -417,7 +417,7 @@ public class UserDaoTest {
assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setKey(property.getKey()).build(), session)).isEmpty();
assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(session, user.getId(), db.getDefaultOrganization().getUuid())).isEmpty();
- assertThat(dbClient.groupMembershipDao().countGroups(session, builder().membership(IN).build(), user.getId())).isZero();
+ assertThat(dbClient.groupMembershipDao().countGroups(session, builder().organizationUuid(db.getDefaultOrganization().getUuid()).membership(IN).build(), user.getId())).isZero();
}
@Test
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java
index e13adec5c81..e6691c3a46e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java
@@ -20,6 +20,8 @@
package org.sonar.server.user.ws;
import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nullable;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
@@ -30,9 +32,12 @@ import org.sonar.api.utils.Paging;
import org.sonar.core.util.Protobuf;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.user.GroupMembershipDto;
import org.sonar.db.user.GroupMembershipQuery;
import org.sonar.db.user.UserDto;
+import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.WsUsers.GroupsWsResponse;
import org.sonarqube.ws.WsUsers.GroupsWsResponse.Group;
@@ -44,17 +49,21 @@ import static org.sonar.api.server.ws.WebService.Param.SELECTED;
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.api.utils.Paging.forPageIndex;
import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN;
+import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_ORGANIZATION;
public class GroupsAction implements UsersWsAction {
private final DbClient dbClient;
private final UserSession userSession;
+ private final DefaultOrganizationProvider defaultOrganizationProvider;
- public GroupsAction(DbClient dbClient, UserSession userSession) {
+ public GroupsAction(DbClient dbClient, UserSession userSession, DefaultOrganizationProvider defaultOrganizationProvider) {
this.dbClient = dbClient;
this.userSession = userSession;
+ this.defaultOrganizationProvider = defaultOrganizationProvider;
}
@Override
@@ -73,26 +82,34 @@ public class GroupsAction implements UsersWsAction {
.setDescription("A user login")
.setExampleValue("admin")
.setRequired(true);
+
+ action.createParam(PARAM_ORGANIZATION)
+ .setDescription("Organization key")
+ .setExampleValue("my-org")
+ .setInternal(true)
+ .setSince("6.4");
}
@Override
public void handle(Request request, Response response) throws Exception {
- userSession.checkLoggedIn().checkIsSystemAdministrator();
GroupsWsResponse groupsWsResponse = doHandle(toGroupsRequest(request));
writeProtobuf(groupsWsResponse, request, response);
}
private GroupsWsResponse doHandle(GroupsRequest request) {
- GroupMembershipQuery query = GroupMembershipQuery.builder()
- .login(request.getLogin())
- .groupSearch(request.getQuery())
- .membership(getMembership(request.getSelected()))
- .pageIndex(request.getPage())
- .pageSize(request.getPageSize())
- .build();
try (DbSession dbSession = dbClient.openSession(false)) {
+ OrganizationDto organization = findOrganizationByKey(dbSession, request.getOrganization());
+ userSession.checkPermission(OrganizationPermission.ADMINISTER, organization);
+
String login = request.getLogin();
+ GroupMembershipQuery query = GroupMembershipQuery.builder()
+ .organizationUuid(organization.getUuid())
+ .groupSearch(request.getQuery())
+ .membership(getMembership(request.getSelected()))
+ .pageIndex(request.getPage())
+ .pageSize(request.getPageSize())
+ .build();
UserDto user = checkFound(dbClient.userDao().selectActiveUserByLogin(dbSession, login), "Unknown user: %s", login);
int total = dbClient.groupMembershipDao().countGroups(dbSession, query, user.getId());
Paging paging = forPageIndex(query.pageIndex()).withPageSize(query.pageSize()).andTotal(total);
@@ -101,9 +118,17 @@ public class GroupsAction implements UsersWsAction {
}
}
+ private OrganizationDto findOrganizationByKey(DbSession dbSession, @Nullable String key) {
+ String effectiveKey = key == null ? defaultOrganizationProvider.get().getKey() : key;
+ Optional<OrganizationDto> org = dbClient.organizationDao().selectByKey(dbSession, effectiveKey);
+ checkFoundWithOptional(org, "No organization with key '%s'", key);
+ return org.get();
+ }
+
private static GroupsRequest toGroupsRequest(Request request) {
return GroupsRequest.builder()
.setLogin(request.mandatoryParam(PARAM_LOGIN))
+ .setOrganization(request.param(PARAM_ORGANIZATION))
.setSelected(request.mandatoryParam(SELECTED))
.setQuery(request.param(TEXT_QUERY))
.setPage(request.mandatoryParamAsInt(PAGE))
diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java
index 99b59f5ee3b..205d54bce0b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/user/ws/GroupsActionTest.java
@@ -26,12 +26,13 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
+import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
@@ -41,59 +42,36 @@ import org.sonarqube.ws.WsUsers.GroupsWsResponse;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
-import static org.mockito.Mockito.mock;
import static org.sonar.api.server.ws.WebService.SelectionMode.ALL;
import static org.sonar.api.server.ws.WebService.SelectionMode.DESELECTED;
import static org.sonar.api.server.ws.WebService.SelectionMode.SELECTED;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.db.user.GroupTesting.newGroupDto;
import static org.sonar.db.user.UserTesting.newUserDto;
import static org.sonar.test.JsonAssert.assertJson;
public class GroupsActionTest {
- private System2 system2 = mock(System2.class);
+ private static final String USER_LOGIN = "john";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
- public DbTester db = DbTester.create(system2);
+ public DbTester db = DbTester.create();
@Rule
- public UserSessionRule userSession = UserSessionRule.standalone().logIn().setSystemAdministrator();
+ public UserSessionRule userSession = UserSessionRule.standalone().logIn().setRoot();
- private WsActionTester ws = new WsActionTester(new GroupsAction(db.getDbClient(), userSession));
+ private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
- @Test
- public void fail_on_unknown_user() throws Exception {
- expectedException.expect(NotFoundException.class);
-
- call(ws.newRequest().setParam("login", "john"));
- }
-
- @Test
- public void fail_on_disabled_user() throws Exception {
- UserDto userDto = db.users().insertUser(user -> user.setActive(false));
-
- expectedException.expect(NotFoundException.class);
-
- call(ws.newRequest().setParam("login", userDto.getLogin()));
- }
-
- @Test
- public void fail_on_missing_permission() throws Exception {
- userSession.logIn("not-admin");
-
- expectedException.expect(ForbiddenException.class);
-
- call(ws.newRequest().setParam("login", "john"));
- }
+ private WsActionTester ws = new WsActionTester(new GroupsAction(db.getDbClient(), userSession, defaultOrganizationProvider));
@Test
public void empty_groups() throws Exception {
insertUser();
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john"));
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN));
assertThat(response.getGroupsList()).isEmpty();
}
@@ -105,7 +83,7 @@ public class GroupsActionTest {
GroupDto adminGroup = insertGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john").setParam(Param.SELECTED, ALL.value()));
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN).setParam(Param.SELECTED, ALL.value()));
assertThat(response.getGroupsList())
.extracting(GroupsWsResponse.Group::getId, GroupsWsResponse.Group::getName, GroupsWsResponse.Group::getDescription, GroupsWsResponse.Group::getSelected)
@@ -121,7 +99,7 @@ public class GroupsActionTest {
insertGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john").setParam(Param.SELECTED, SELECTED.value()));
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN).setParam(Param.SELECTED, SELECTED.value()));
assertThat(response.getGroupsList())
.extracting(GroupsWsResponse.Group::getId, GroupsWsResponse.Group::getName, GroupsWsResponse.Group::getDescription, GroupsWsResponse.Group::getSelected)
@@ -135,7 +113,7 @@ public class GroupsActionTest {
insertGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john"));
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN));
assertThat(response.getGroupsList())
.extracting(GroupsWsResponse.Group::getId, GroupsWsResponse.Group::getName, GroupsWsResponse.Group::getDescription, GroupsWsResponse.Group::getSelected)
@@ -149,7 +127,7 @@ public class GroupsActionTest {
GroupDto adminGroup = insertGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john").setParam(Param.SELECTED, DESELECTED.value()));
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN).setParam(Param.SELECTED, DESELECTED.value()));
assertThat(response.getGroupsList())
.extracting(GroupsWsResponse.Group::getId, GroupsWsResponse.Group::getName, GroupsWsResponse.Group::getDescription, GroupsWsResponse.Group::getSelected)
@@ -175,7 +153,7 @@ public class GroupsActionTest {
addUserToGroup(user, groupDto);
}
- GroupsWsResponse response = call(ws.newRequest().setParam("login", "john")
+ GroupsWsResponse response = call(ws.newRequest().setParam("login", USER_LOGIN)
.setParam(Param.PAGE_SIZE, "3")
.setParam(Param.PAGE, "2")
.setParam(Param.SELECTED, ALL.value()));
@@ -193,13 +171,80 @@ public class GroupsActionTest {
GroupDto adminGroup = insertGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
- assertThat(call(ws.newRequest().setParam("login", "john").setParam("q", "admin").setParam(Param.SELECTED, ALL.value())).getGroupsList())
+ assertThat(call(ws.newRequest().setParam("login", USER_LOGIN).setParam("q", "admin").setParam(Param.SELECTED, ALL.value())).getGroupsList())
.extracting(GroupsWsResponse.Group::getName).containsOnly(adminGroup.getName());
- assertThat(call(ws.newRequest().setParam("login", "john").setParam("q", "users").setParam(Param.SELECTED, ALL.value())).getGroupsList())
+ assertThat(call(ws.newRequest().setParam("login", USER_LOGIN).setParam("q", "users").setParam(Param.SELECTED, ALL.value())).getGroupsList())
.extracting(GroupsWsResponse.Group::getName).containsOnly(usersGroup.getName());
}
@Test
+ public void return_groups_from_given_organization() throws Exception {
+ UserDto user = insertUser();
+ OrganizationDto organizationDto = db.organizations().insert();
+ OrganizationDto otherOrganizationDto = db.organizations().insert();
+ GroupDto group = db.users().insertGroup(organizationDto, "group1");
+ GroupDto otherGroup = db.users().insertGroup(otherOrganizationDto, "group2");
+ addUserToGroup(user, group);
+ addUserToGroup(user, otherGroup);
+
+ GroupsWsResponse response = call(ws.newRequest()
+ .setParam("login", USER_LOGIN)
+ .setParam("organization", organizationDto.getKey())
+ .setParam(Param.SELECTED, ALL.value()));
+
+ assertThat(response.getGroupsList())
+ .extracting(GroupsWsResponse.Group::getId, GroupsWsResponse.Group::getName, GroupsWsResponse.Group::getDescription, GroupsWsResponse.Group::getSelected)
+ .containsOnly(tuple(group.getId().longValue(), group.getName(), group.getDescription(), true));
+ }
+
+ @Test
+ public void fail_on_unknown_user() throws Exception {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Unknown user: john");
+
+ call(ws.newRequest().setParam("login", USER_LOGIN));
+ }
+
+ @Test
+ public void fail_on_disabled_user() throws Exception {
+ UserDto userDto = db.users().insertUser(user -> user.setLogin("disabled").setActive(false));
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Unknown user: disabled");
+
+ call(ws.newRequest().setParam("login", userDto.getLogin()));
+ }
+
+ @Test
+ public void fail_on_unknown_organization() throws Exception {
+ insertUser();
+
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("No organization with key 'unknown'");
+
+ call(ws.newRequest().setParam("login", USER_LOGIN).setParam("organization", "unknown"));
+ }
+
+ @Test
+ public void fail_on_missing_permission() throws Exception {
+ OrganizationDto organizationDto = db.organizations().insert();
+ userSession.logIn().addPermission(ADMINISTER, organizationDto);
+
+ expectedException.expect(ForbiddenException.class);
+
+ call(ws.newRequest().setParam("login", USER_LOGIN));
+ }
+
+ @Test
+ public void fail_when_no_permission() throws Exception {
+ userSession.logIn("not-admin");
+
+ expectedException.expect(ForbiddenException.class);
+
+ call(ws.newRequest().setParam("login", USER_LOGIN));
+ }
+
+ @Test
public void test_json_example() {
UserDto user = insertUser();
GroupDto usersGroup = insertGroup("sonar-users", "Sonar Users");
@@ -208,7 +253,7 @@ public class GroupsActionTest {
String response = ws.newRequest()
.setMediaType(MediaTypes.JSON)
- .setParam("login", "john")
+ .setParam("login", USER_LOGIN)
.setParam(Param.SELECTED, ALL.value())
.setParam(Param.PAGE_SIZE, "25")
.setParam(Param.PAGE, "1")
@@ -225,14 +270,21 @@ public class GroupsActionTest {
assertThat(action.isInternal()).isFalse();
assertThat(action.responseExampleAsString()).isNotEmpty();
- assertThat(action.params()).extracting(Param::key).containsOnly("p", "q", "ps", "login", "selected");
+ assertThat(action.params()).extracting(Param::key).containsOnly("p", "q", "ps", "login", "selected", "organization");
WebService.Param qualifiers = action.param("login");
assertThat(qualifiers.isRequired()).isTrue();
+
+ WebService.Param organization = action.param("organization");
+ assertThat(organization.isRequired()).isFalse();
+ assertThat(organization.description()).isEqualTo("Organization key");
+ assertThat(organization.isInternal()).isTrue();
+ assertThat(organization.exampleValue()).isEqualTo("my-org");
+ assertThat(organization.since()).isEqualTo("6.4");
}
private GroupDto insertGroup(String name, String description) {
- return db.users().insertGroup(newGroupDto().setName(name).setDescription(description));
+ return db.users().insertGroup(newGroupDto().setName(name).setDescription(description).setOrganizationUuid(db.getDefaultOrganization().getUuid()));
}
private void addUserToGroup(UserDto user, GroupDto usersGroup) {
@@ -243,7 +295,7 @@ public class GroupsActionTest {
return db.users().insertUser(newUserDto()
.setActive(true)
.setEmail("john@email.com")
- .setLogin("john")
+ .setLogin(USER_LOGIN)
.setName("John")
.setScmAccounts(singletonList("jn")));
}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/GroupsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/GroupsRequest.java
index 4b44f65ff43..161a388e385 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/GroupsRequest.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/GroupsRequest.java
@@ -30,6 +30,7 @@ import static com.google.common.base.Strings.isNullOrEmpty;
public class GroupsRequest {
private final String login;
+ private final String organization;
private final String query;
private final String selected;
private final Integer page;
@@ -37,6 +38,7 @@ public class GroupsRequest {
private GroupsRequest(Builder builder) {
this.login = builder.login;
+ this.organization = builder.organization;
this.query = builder.query;
this.selected = builder.selected;
this.page = builder.page;
@@ -48,6 +50,11 @@ public class GroupsRequest {
}
@CheckForNull
+ public String getOrganization() {
+ return organization;
+ }
+
+ @CheckForNull
public String getQuery() {
return query;
}
@@ -73,6 +80,7 @@ public class GroupsRequest {
public static class Builder {
private String login;
+ private String organization;
private String query;
private String selected;
private Integer page;
@@ -87,6 +95,11 @@ public class GroupsRequest {
return this;
}
+ public Builder setOrganization(@Nullable String organization) {
+ this.organization = organization;
+ return this;
+ }
+
public Builder setQuery(@Nullable String query) {
this.query = query;
return this;
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersService.java
index 1a55512f6e0..d984c5ea55b 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersService.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersService.java
@@ -37,6 +37,7 @@ import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_EMAIL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOCAL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_PASSWORD;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_SCM_ACCOUNT;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_SELECTED;
@@ -69,6 +70,7 @@ public class UsersService extends BaseService {
public GroupsWsResponse groups(GroupsRequest request) {
return call(new GetRequest(path(ACTION_GROUPS))
.setParam(PARAM_LOGIN, request.getLogin())
+ .setParam(PARAM_ORGANIZATION, request.getOrganization())
.setParam(PARAM_SELECTED, request.getSelected())
.setParam(TEXT_QUERY, request.getQuery())
.setParam(PAGE, request.getPage())
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersWsParameters.java
index cf1946786b3..ba674caf9d3 100644
--- a/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersWsParameters.java
+++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/user/UsersWsParameters.java
@@ -27,6 +27,7 @@ public class UsersWsParameters {
public static final String ACTION_UPDATE = "update";
public static final String ACTION_GROUPS = "groups";
+ public static final String PARAM_ORGANIZATION = "organization";
public static final String PARAM_LOGIN = "login";
public static final String PARAM_PASSWORD = "password";
public static final String PARAM_NAME = "name";
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/user/GroupsRequestTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/user/GroupsRequestTest.java
index 082e5f720b6..58270e89608 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/user/GroupsRequestTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/user/GroupsRequestTest.java
@@ -37,6 +37,7 @@ public class GroupsRequestTest {
public void create_request() {
GroupsRequest result = underTest
.setLogin("john")
+ .setOrganization("orga-uuid")
.setSelected("all")
.setQuery("sonar-users")
.setPage(10)
@@ -44,6 +45,7 @@ public class GroupsRequestTest {
.build();
assertThat(result.getLogin()).isEqualTo("john");
+ assertThat(result.getOrganization()).isEqualTo("orga-uuid");
assertThat(result.getSelected()).isEqualTo("all");
assertThat(result.getQuery()).isEqualTo("sonar-users");
assertThat(result.getPage()).isEqualTo(10);
@@ -52,9 +54,12 @@ public class GroupsRequestTest {
@Test
public void create_request_wih_minimal_fields() {
- GroupsRequest result = underTest.setLogin("john").build();
+ GroupsRequest result = underTest
+ .setLogin("john")
+ .build();
assertThat(result.getLogin()).isEqualTo("john");
+ assertThat(result.getOrganization()).isNull();
assertThat(result.getSelected()).isNull();
assertThat(result.getQuery()).isNull();
assertThat(result.getPage()).isNull();
@@ -66,9 +71,7 @@ public class GroupsRequestTest {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Login is mandatory and must not be empty");
- underTest
- .setLogin("")
- .build();
+ underTest.setLogin("").build();
}
@Test
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/user/UsersServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/user/UsersServiceTest.java
index 37902de632c..c92f7619ffe 100644
--- a/sonar-ws/src/test/java/org/sonarqube/ws/client/user/UsersServiceTest.java
+++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/user/UsersServiceTest.java
@@ -36,6 +36,7 @@ import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_EMAIL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOCAL;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_LOGIN;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_NAME;
+import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_PASSWORD;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_SCM_ACCOUNT;
import static org.sonarqube.ws.client.user.UsersWsParameters.PARAM_SELECTED;
@@ -90,6 +91,7 @@ public class UsersServiceTest {
public void groups() {
underTest.groups(GroupsRequest.builder()
.setLogin("john")
+ .setOrganization("orga-uuid")
.setSelected("all")
.setQuery("sonar-users")
.setPage(10)
@@ -99,6 +101,7 @@ public class UsersServiceTest {
assertThat(serviceTester.getGetParser()).isSameAs(GroupsWsResponse.parser());
serviceTester.assertThat(serviceTester.getGetRequest())
.hasParam(PARAM_LOGIN, "john")
+ .hasParam(PARAM_ORGANIZATION, "orga-uuid")
.hasParam(PARAM_SELECTED, "all")
.hasParam(TEXT_QUERY, "sonar-users")
.hasParam(PAGE, 10)