package org.sonar.server.organization.ws;
import java.util.List;
+import java.util.Set;
import javax.annotation.CheckForNull;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonarqube.ws.Organizations;
import org.sonarqube.ws.Organizations.Organization;
+import static java.util.Collections.emptySet;
+import static org.sonar.core.util.stream.MoreCollectors.toSet;
import static org.sonar.db.Pagination.forPage;
import static org.sonar.db.organization.OrganizationQuery.newOrganizationQueryBuilder;
-import static org.sonar.server.ws.WsUtils.checkRequest;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.Common.Paging;
action.createParam(PARAM_ORGANIZATIONS)
.setDescription("Comma-separated list of organization keys")
.setExampleValue(String.join(",", "my-org-1", "foocorp"))
- .setMinimumLength(2)
+ .setMaxValuesAllowed(MAX_SIZE)
.setRequired(false)
.setSince("6.3");
@Override
public void handle(Request request, Response response) throws Exception {
try (DbSession dbSession = dbClient.openSession(false)) {
- Integer userId = getUserIdIfFilterMembership(request);
- List<String> organizations = getOrganizationKeys(request);
- OrganizationQuery dbQuery = newOrganizationQueryBuilder()
- .setKeys(organizations)
- .setMember(userId)
- .build();
-
+ OrganizationQuery dbQuery = buildDbQuery(request);
int total = dbClient.organizationDao().countByQuery(dbSession, dbQuery);
Paging paging = buildWsPaging(request, total);
- List<OrganizationDto> dtos = dbClient.organizationDao().selectByQuery(
- dbSession,
- dbQuery,
- forPage(paging.getPageIndex()).andSize(paging.getPageSize()));
- writeResponse(request, response, dtos, paging);
+ List<OrganizationDto> organizations = dbClient.organizationDao().selectByQuery(dbSession, dbQuery, forPage(paging.getPageIndex()).andSize(paging.getPageSize()));
+ Set<String> adminOrganizationUuids = searchOrganizationWithAdminPermission(dbSession);
+ writeResponse(request, response, organizations, adminOrganizationUuids, paging);
}
}
- private void writeResponse(Request request, Response response, List<OrganizationDto> dtos, Paging paging) {
- Organizations.SearchWsResponse.Builder responseBuilder = Organizations.SearchWsResponse.newBuilder();
- responseBuilder.setPaging(paging);
- Organization.Builder organizationBuilder = Organization.newBuilder();
- dtos.forEach(dto -> responseBuilder.addOrganizations(wsSupport.toOrganization(organizationBuilder, dto)));
- writeProtobuf(responseBuilder.build(), request, response);
+ private OrganizationQuery buildDbQuery(Request request) {
+ return newOrganizationQueryBuilder()
+ .setKeys(request.paramAsStrings(PARAM_ORGANIZATIONS))
+ .setMember(getUserIdIfFilterOnMembership(request))
+ .build();
+ }
+
+ private Set<String> searchOrganizationWithAdminPermission(DbSession dbSession) {
+ Integer userId = userSession.getUserId();
+ return userId == null ? emptySet()
+ : dbClient.organizationDao().selectByPermission(dbSession, userId, ADMINISTER.getKey()).stream().map(OrganizationDto::getUuid).collect(toSet());
+ }
+
+ private void writeResponse(Request httpRequest, Response httpResponse, List<OrganizationDto> organizations, Set<String> adminOrganizationUuids, Paging paging) {
+ Organizations.SearchWsResponse.Builder response = Organizations.SearchWsResponse.newBuilder();
+ response.setPaging(paging);
+ Organization.Builder wsOrganization = Organization.newBuilder();
+ organizations
+ .forEach(o -> {
+ boolean isAdmin = adminOrganizationUuids.contains(o.getUuid());
+ wsOrganization.clear();
+ wsOrganization.setIsAdmin(isAdmin);
+ response.addOrganizations(wsSupport.toOrganization(wsOrganization, o));
+ });
+ writeProtobuf(response.build(), httpRequest, httpResponse);
}
private static Paging buildWsPaging(Request request, int total) {
}
@CheckForNull
- private Integer getUserIdIfFilterMembership(Request request) {
+ private Integer getUserIdIfFilterOnMembership(Request request) {
boolean filterOnAuthenticatedUser = request.mandatoryParamAsBoolean(PARAM_MEMBER);
- if (!filterOnAuthenticatedUser) {
- return null;
- }
-
- userSession.checkLoggedIn();
- return userSession.getUserId();
- }
-
- @CheckForNull
- private static List<String> getOrganizationKeys(Request request) {
- List<String> organizations = request.paramAsStrings(PARAM_ORGANIZATIONS);
- if (organizations != null) {
- checkRequest(organizations.size() <= MAX_SIZE, "Size of '%s' (%d) must be less than %d", PARAM_ORGANIZATIONS, organizations.size(), MAX_SIZE);
- }
- return organizations;
+ return (userSession.isLoggedIn() && filterOnAuthenticatedUser) ? userSession.getUserId() : null;
}
-
}
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.core.util.Uuids;
-import org.sonar.db.DbSession;
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.organization.OrganizationValidationImpl;
import org.sonar.server.tester.UserSessionRule;
import static java.lang.String.valueOf;
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.mockito.Mockito.when;
+import static org.sonar.db.permission.OrganizationPermission.ADMINISTER;
import static org.sonar.server.organization.ws.SearchAction.PARAM_MEMBER;
import static org.sonar.test.JsonAssert.assertJson;
assertThat(organizations.description()).isEqualTo("Comma-separated list of organization keys");
assertThat(organizations.exampleValue()).isEqualTo("my-org-1,foocorp");
assertThat(organizations.since()).isEqualTo("6.3");
+ assertThat(organizations.maxValuesAllowed()).isEqualTo(500);
WebService.Param page = action.param("p");
assertThat(page.isRequired()).isFalse();
}
@Test
- public void verify_response_example() throws URISyntaxException, IOException {
+ public void json_example() throws URISyntaxException, IOException {
when(system2.now()).thenReturn(SOME_DATE, SOME_DATE + 1000);
- insertOrganization(new OrganizationDto()
+ OrganizationDto barOrganization = db.organizations().insert(new OrganizationDto()
.setUuid(Uuids.UUID_EXAMPLE_02)
.setKey("bar-company")
.setName("Bar Company")
.setUrl("https://www.bar.com")
.setAvatarUrl("https://www.bar.com/logo.png")
.setGuarded(false));
- insertOrganization(new OrganizationDto()
+ OrganizationDto fooOrganization = db.organizations().insert(new OrganizationDto()
.setUuid(Uuids.UUID_EXAMPLE_01)
.setKey("foo-company")
.setName("Foo Company")
.setGuarded(true));
+ UserDto user = db.users().insertUser();
+ db.organizations().addMember(barOrganization, user);
+ db.organizations().addMember(fooOrganization, user);
+ db.users().insertPermissionOnUser(barOrganization, user, ADMINISTER);
+ userSession.logIn(user).addPermission(ADMINISTER, barOrganization);
TestRequest request = ws.newRequest()
.setMediaType(MediaTypes.JSON);
populateRequest(request, null, 25);
- String response = request.execute().getInput();
+ String result = request.execute().getInput();
- assertJson(response).isSimilarTo(ws.getDef().responseExampleAsString());
+ assertJson(ws.getDef().responseExampleAsString()).isSimilarTo(result);
+ assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
+ }
+
+ @Test
+ public void is_admin_available_for_each_organization() {
+ OrganizationDto userAdminOrganization = db.organizations().insert();
+ OrganizationDto groupAdminOrganization = db.organizations().insert();
+ OrganizationDto browseOrganization = db.organizations().insert();
+ UserDto user = db.users().insertUser();
+ GroupDto group = db.users().insertGroup(groupAdminOrganization);
+ db.users().insertMember(group, user);
+ userSession.logIn(user).addPermission(ADMINISTER, userAdminOrganization);
+ db.users().insertPermissionOnUser(userAdminOrganization, user, ADMINISTER);
+ db.users().insertPermissionOnGroup(group, ADMINISTER);
+
+ SearchWsResponse result = call(ws.newRequest());
+
+ assertThat(result.getOrganizationsList()).extracting(Organization::getKey, Organization::getIsAdmin).containsExactlyInAnyOrder(
+ tuple(userAdminOrganization.getKey(), true),
+ tuple(browseOrganization.getKey(), false),
+ tuple(groupAdminOrganization.getKey(), true));
}
@Test
@Test
public void request_returns_empty_on_table_with_single_row_when_not_requesting_the_first_page() {
when(system2.now()).thenReturn(SOME_DATE);
- insertOrganization(ORGANIZATION_DTO);
+ db.organizations().insert(ORGANIZATION_DTO);
assertThat(executeRequestAndReturnList(2, null)).isEmpty();
assertThat(executeRequestAndReturnList(2, 1)).isEmpty();
@Test
public void request_returns_rows_ordered_by_createdAt_descending_applying_requested_paging() {
when(system2.now()).thenReturn(SOME_DATE, SOME_DATE + 1_000, SOME_DATE + 2_000, SOME_DATE + 3_000, SOME_DATE + 5_000);
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
assertThat(executeRequestAndReturnList(1, 1))
.extracting(Organization::getKey)
@Test
public void request_returns_only_specified_keys_ordered_by_createdAt_when_filtering_keys() {
when(system2.now()).thenReturn(SOME_DATE, SOME_DATE + 1_000, SOME_DATE + 2_000, SOME_DATE + 3_000, SOME_DATE + 5_000);
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
assertThat(executeRequestAndReturnList(1, 10, "key-3", "key-1", "key-5"))
.extracting(Organization::getKey)
@Test
public void result_is_paginated() {
when(system2.now()).thenReturn(SOME_DATE, SOME_DATE + 1_000, SOME_DATE + 2_000, SOME_DATE + 3_000, SOME_DATE + 5_000);
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
- insertOrganization(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid3").setKey("key-3"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid1").setKey("key-1"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid2").setKey("key-2"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid5").setKey("key-5"));
+ db.organizations().insert(ORGANIZATION_DTO.setUuid("uuid4").setKey("key-4"));
SearchWsResponse response = call(1, 1, "key-1", "key-3", "key-5");
assertThat(response.getOrganizationsList()).extracting(Organization::getKey).containsOnly("key-5");
@Test
public void request_returns_empty_when_filtering_on_non_existing_key() {
when(system2.now()).thenReturn(SOME_DATE);
- insertOrganization(ORGANIZATION_DTO);
+ db.organizations().insert(ORGANIZATION_DTO);
assertThat(executeRequestAndReturnList(1, 10, ORGANIZATION_DTO.getKey()))
.extracting(Organization::getKey)
return request.executeProtobuf(SearchWsResponse.class);
}
- private void insertOrganization(OrganizationDto dto) {
- DbSession dbSession = db.getSession();
- db.getDbClient().organizationDao().insert(dbSession, dto, false);
- dbSession.commit();
- }
-
private SearchWsResponse call(@Nullable Integer page, @Nullable Integer pageSize, String... keys) {
TestRequest request = ws.newRequest();
populateRequest(request, page, pageSize, keys);