aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.gradle6
-rw-r--r--plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/architecture/ArchitectureSensor.java12
-rw-r--r--server/sonar-db-dao/src/it/java/org/sonar/db/user/GroupDaoIT.java41
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupQuery.java31
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMapper.xml6
-rw-r--r--server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java2
-rw-r--r--server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupSearchRequest.java2
-rw-r--r--server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java2
-rw-r--r--server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java33
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/DefaultGroupController.java6
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/GroupController.java7
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/request/GroupsSearchRestRequest.java9
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGenerator.java4
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForAnonymousUsers.java1
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForLoggedInUsers.java7
-rw-r--r--server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/group/controller/DefaultGroupControllerTest.java6
-rw-r--r--server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGeneratorTest.java5
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java7
18 files changed, 147 insertions, 40 deletions
diff --git a/build.gradle b/build.gradle
index 9d0939f3ab4..470d8333f2a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -314,12 +314,12 @@ subprojects {
dependency 'org.sonarsource.jacoco:sonar-jacoco-plugin:1.3.0.1538'
dependency 'org.sonarsource.java:sonar-java-plugin:8.13.0.38826'
dependency 'org.sonarsource.java:sonar-java-symbolic-execution-plugin:8.13.0.38826'
- dependency 'org.sonarsource.javascript:sonar-javascript-plugin:10.22.0.32148'
+ dependency 'org.sonarsource.javascript:sonar-javascript-plugin:10.23.0.32711'
dependency 'org.sonarsource.php:sonar-php-plugin:3.45.0.12991'
dependency 'org.sonarsource.plugins.cayc:sonar-cayc-plugin:2.4.0.2018'
- dependency 'org.sonarsource.python:sonar-python-plugin:5.2.0.20808'
+ dependency 'org.sonarsource.python:sonar-python-plugin:5.4.0.22255'
dependency 'org.sonarsource.rust:sonar-rust-plugin:1.0.2.734'
- dependency 'com.sonarsource.python:sonar-python-enterprise-plugin:5.2.0.20808'
+ dependency 'com.sonarsource.python:sonar-python-enterprise-plugin:5.4.0.22255'
dependency 'org.sonarsource.kotlin:sonar-kotlin-plugin:3.1.0.7071'
dependency "org.sonarsource.api.plugin:sonar-plugin-api:$pluginApiVersion"
dependency "org.sonarsource.api.plugin:sonar-plugin-api-test-fixtures:$pluginApiVersion"
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/architecture/ArchitectureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/architecture/ArchitectureSensor.java
index 2f7d1f8c961..237f8fa71ba 100644
--- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/architecture/ArchitectureSensor.java
+++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/architecture/ArchitectureSensor.java
@@ -44,23 +44,23 @@ public class ArchitectureSensor implements ProjectSensor {
.count();
context.addAnalysisData(
- "architecture.graph.java.file_graph",
+ "architecture.graph." + Xoo.KEY + ".file_graph",
mimeType,
- new ByteArrayInputStream(("{\"graph\":\"data\", \"classCount\":" + count + "}")
+ new ByteArrayInputStream(("{\"graph\":\"files\", \"fileCount\":" + count + "}")
.getBytes(StandardCharsets.UTF_8))
);
context.addAnalysisData(
- "architecture.graph." + Xoo.KEY + ".file_graph",
+ "architecture.graph." + Xoo.KEY + ".file_graph.module_persp",
mimeType,
- new ByteArrayInputStream(("{\"graph\":\"data\", \"fileCount\":" + count + "}")
+ new ByteArrayInputStream(("{\"graph\":\"modules\", \"fileCount\":" + count + "}")
.getBytes(StandardCharsets.UTF_8))
);
context.addAnalysisData(
- "architecture.graph." + Xoo.KEY + ".file_graph.module_persp",
+ "architecture.graph." + Xoo.KEY + ".namespace",
mimeType,
- new ByteArrayInputStream(("{\"graph\":\"data\", \"moduleCount\":" + count + "}")
+ new ByteArrayInputStream(("{\"graph\":\"namespace\", \"fileCount\":" + count + "}")
.getBytes(StandardCharsets.UTF_8))
);
}
diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/user/GroupDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/user/GroupDaoIT.java
index 9b52c0d7264..16e86bcd2e5 100644
--- a/server/sonar-db-dao/src/it/java/org/sonar/db/user/GroupDaoIT.java
+++ b/server/sonar-db-dao/src/it/java/org/sonar/db/user/GroupDaoIT.java
@@ -223,6 +223,47 @@ class GroupDaoIT {
}
@Test
+ void findByQuery_withUserId_countAndFindExpectedUsers() {
+ GroupDto group1 = db.users().insertGroup("sonar-users");
+ GroupDto group2 = db.users().insertGroup("SONAR-ADMINS");
+ GroupDto group3 = db.users().insertGroup("customers-group1");
+
+ UserDto user = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ db.users().insertMember(group1, user);
+ db.users().insertMember(group2, user);
+ db.users().insertMember(group2, user2);
+ db.users().insertMember(group3, user2);
+
+ GroupQuery groupQueryIncludingUser = GroupQuery.builder().userId(user.getUuid()).build();
+
+ assertThat(underTest.countByQuery(dbSession, groupQueryIncludingUser)).isEqualTo(2);
+ assertThat(underTest.selectByQuery(dbSession, groupQueryIncludingUser, 1, 100))
+ .extracting(GroupDto::getUuid)
+ .containsExactlyInAnyOrder(group1.getUuid(), group2.getUuid());
+ }
+
+ @Test
+ void findByQuery_withExcludedUserId_countAndFindExpectedUsers() {
+ GroupDto group1 = db.users().insertGroup("sonar-users");
+ GroupDto group2 = db.users().insertGroup("SONAR-ADMINS");
+ GroupDto group3 = db.users().insertGroup("customers-group1");
+
+ UserDto user = db.users().insertUser();
+ UserDto user2 = db.users().insertUser();
+ db.users().insertMember(group1, user);
+ db.users().insertMember(group2, user);
+ db.users().insertMember(group2, user2);
+ db.users().insertMember(group3, user2);
+
+ GroupQuery groupQueryExcludingUser = GroupQuery.builder().excludedUserId(user.getUuid()).build();
+ assertThat(underTest.countByQuery(dbSession, groupQueryExcludingUser)).isEqualTo(1);
+ assertThat(underTest.selectByQuery(dbSession, groupQueryExcludingUser, 1, 100))
+ .extracting(GroupDto::getUuid)
+ .containsExactlyInAnyOrder(group3.getUuid());
+ }
+
+ @Test
void deleteByUuid() {
db.getDbClient().groupDao().insert(dbSession, aGroup);
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupQuery.java
index a2185648d6b..b54c25da22d 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupQuery.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/user/GroupQuery.java
@@ -29,10 +29,14 @@ import org.sonar.db.WildcardPosition;
public class GroupQuery {
private final String searchText;
private final String isManagedSqlClause;
+ private final String userId;
+ private final String excludedUserId;
- GroupQuery(@Nullable String searchText, @Nullable String isManagedSqlClause) {
+ GroupQuery(@Nullable String searchText, @Nullable String isManagedSqlClause, String userId, String excludedUserId) {
this.searchText = searchTextToSearchTextSql(searchText);
this.isManagedSqlClause = isManagedSqlClause;
+ this.userId = userId;
+ this.excludedUserId = excludedUserId;
}
private static String searchTextToSearchTextSql(@Nullable String text) {
@@ -54,6 +58,16 @@ public class GroupQuery {
return isManagedSqlClause;
}
+ @CheckForNull
+ public String getUserId() {
+ return userId;
+ }
+
+ @CheckForNull
+ public String getExcludedUserId() {
+ return excludedUserId;
+ }
+
public static GroupQueryBuilder builder() {
return new GroupQueryBuilder();
}
@@ -61,6 +75,8 @@ public class GroupQuery {
public static final class GroupQueryBuilder {
private String searchText = null;
private String isManagedSqlClause = null;
+ private String userId = null;
+ private String excludedUserId = null;
private GroupQueryBuilder() {
}
@@ -70,14 +86,23 @@ public class GroupQuery {
return this;
}
-
public GroupQuery.GroupQueryBuilder isManagedClause(@Nullable String isManagedSqlClause) {
this.isManagedSqlClause = isManagedSqlClause;
return this;
}
+ public GroupQuery.GroupQueryBuilder userId(@Nullable String userId) {
+ this.userId = userId;
+ return this;
+ }
+
+ public GroupQuery.GroupQueryBuilder excludedUserId(@Nullable String excludedUserId) {
+ this.excludedUserId = excludedUserId;
+ return this;
+ }
+
public GroupQuery build() {
- return new GroupQuery(searchText, isManagedSqlClause);
+ return new GroupQuery(searchText, isManagedSqlClause, userId, excludedUserId);
}
}
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMapper.xml
index 7adc671389e..87ed608b98a 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMapper.xml
@@ -113,6 +113,12 @@
<if test="query.isManagedSqlClause != null">
AND ${query.isManagedSqlClause}
</if>
+ <if test="query.userId != null">
+ AND g.uuid in (select group_uuid from groups_users gu where gu.user_uuid = #{query.userId,jdbcType=VARCHAR})
+ </if>
+ <if test="query.excludedUserId != null">
+ AND g.uuid not in (select group_uuid from groups_users gu where gu.user_uuid = #{query.excludedUserId,jdbcType=VARCHAR})
+ </if>
</where>
</sql>
</mapper>
diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
index 26dcfbab451..d1ee49895e2 100644
--- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
+++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/user/UserDbTester.java
@@ -208,7 +208,7 @@ public class UserDbTester {
}
public int countAllGroups() {
- return db.getDbClient().groupDao().countByQuery(db.getSession(), new GroupQuery(null, null));
+ return db.getDbClient().groupDao().countByQuery(db.getSession(), new GroupQuery(null, null, null, null));
}
public Optional<ExternalGroupDto> selectExternalGroupByGroupUuid(String groupUuid) {
diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupSearchRequest.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupSearchRequest.java
index 1ef6af378a1..816b971f540 100644
--- a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupSearchRequest.java
+++ b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupSearchRequest.java
@@ -24,6 +24,8 @@ import javax.annotation.Nullable;
public record GroupSearchRequest(
@Nullable String query,
@Nullable Boolean managed,
+ @Nullable String userUuid,
+ @Nullable String excludedUserUuid,
int page,
int pageSize
) {
diff --git a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java
index fac6c4bb711..2801c905d82 100644
--- a/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java
+++ b/server/sonar-webserver-common/src/main/java/org/sonar/server/common/group/service/GroupService.java
@@ -93,6 +93,8 @@ public class GroupService {
return GroupQuery.builder()
.searchText(groupSearchRequest.query())
.isManagedClause(getManagedInstanceSql(groupSearchRequest.managed()))
+ .userId(groupSearchRequest.userUuid())
+ .excludedUserId(groupSearchRequest.excludedUserUuid())
.build();
}
diff --git a/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java b/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java
index 02a37273efa..bafc6e7431d 100644
--- a/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java
+++ b/server/sonar-webserver-common/src/test/java/org/sonar/server/common/group/service/GroupServiceTest.java
@@ -316,7 +316,7 @@ public class GroupServiceTest {
public void createGroup_whenNameAndDescriptionIsProvided_createsGroup() {
when(uuidFactory.create()).thenReturn("1234");
- GroupDto createdGroup = mockGroupDto();
+ GroupDto createdGroup = mockGroupDto();
when(dbClient.groupDao().insert(eq(dbSession), any())).thenReturn(createdGroup);
mockDefaultGroup();
groupService.createGroup(dbSession, "Name", "Description");
@@ -378,7 +378,7 @@ public class GroupServiceTest {
when(dbClient.groupDao().countByQuery(eq(dbSession), any())).thenReturn(300);
- SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, 5, 24));
+ SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, null, null, 5, 24));
assertThat(searchResults.total()).isEqualTo(300);
Map<String, GroupInformation> uuidToGroupInformation = searchResults.searchResults().stream()
@@ -390,11 +390,12 @@ public class GroupServiceTest {
assertThat(queryCaptor.getValue().getSearchText()).isEqualTo("%QUERY%");
assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isNull();
}
+
@Test
public void search_whenPageSizeEquals0_returnsOnlyTotal() {
when(dbClient.groupDao().countByQuery(eq(dbSession), any())).thenReturn(10);
- SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, 0, 24));
+ SearchResults<GroupInformation> searchResults = groupService.search(dbSession, new GroupSearchRequest("query", null, null, null, 0, 24));
assertThat(searchResults.total()).isEqualTo(10);
assertThat(searchResults.searchResults()).isEmpty();
@@ -406,7 +407,7 @@ public class GroupServiceTest {
mockManagedInstance();
when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
- groupService.search(dbSession, new GroupSearchRequest("query", true, 5, 24));
+ groupService.search(dbSession, new GroupSearchRequest("query", true, null, null, 5, 24));
assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isEqualTo("managed_filter");
}
@@ -416,7 +417,7 @@ public class GroupServiceTest {
mockManagedInstance();
when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
- groupService.search(dbSession, new GroupSearchRequest("query", false, 5, 24));
+ groupService.search(dbSession, new GroupSearchRequest("query", false, null, null, 5, 24));
assertThat(queryCaptor.getValue().getIsManagedSqlClause()).isEqualTo("not_managed_filter");
}
@@ -424,7 +425,7 @@ public class GroupServiceTest {
@Test
public void search_whenInstanceNotManagedAndManagedIsTrue_throws() {
assertThatExceptionOfType(BadRequestException.class)
- .isThrownBy(() -> groupService.search(dbSession, new GroupSearchRequest("query", true, 5, 24)))
+ .isThrownBy(() -> groupService.search(dbSession, new GroupSearchRequest("query", true, null, null, 5, 24)))
.withMessage("The 'managed' parameter is only available for managed instances.");
}
@@ -434,6 +435,26 @@ public class GroupServiceTest {
when(managedInstanceService.getManagedGroupsSqlFilter(false)).thenReturn("not_managed_filter");
}
+ @Test
+ public void search_whenUserIdParameterProvided_addsItToQuery() {
+ when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
+
+ groupService.search(dbSession, new GroupSearchRequest("query", null, "includedUserUuid", null, 5, 24));
+
+ assertThat(queryCaptor.getValue().getUserId()).isEqualTo("includedUserUuid");
+ assertThat(queryCaptor.getValue().getExcludedUserId()).isNull();
+ }
+
+ @Test
+ public void search_whenExcludedUserIdParameterProvided_addsItToQuery() {
+ when(dbClient.groupDao().selectByQuery(eq(dbSession), queryCaptor.capture(), anyInt(), anyInt())).thenReturn(List.of());
+
+ groupService.search(dbSession, new GroupSearchRequest("query", null, null, "excludedUserId", 5, 24));
+
+ assertThat(queryCaptor.getValue().getUserId()).isNull();
+ assertThat(queryCaptor.getValue().getExcludedUserId()).isEqualTo("excludedUserId");
+ }
+
private static void assertGroupInformation(Map<String, GroupInformation> uuidToGroupInformation, GroupDto expectedGroupDto, boolean expectedManaged, boolean expectedDefault) {
assertThat(uuidToGroupInformation.get(expectedGroupDto.getUuid()).groupDto()).isEqualTo(expectedGroupDto);
assertThat(uuidToGroupInformation.get(expectedGroupDto.getUuid()).isManaged()).isEqualTo(expectedManaged);
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/DefaultGroupController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/DefaultGroupController.java
index 1b5b17e5e6a..9727e3b7d04 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/DefaultGroupController.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/DefaultGroupController.java
@@ -20,6 +20,7 @@
package org.sonar.server.v2.api.group.controller;
import java.util.List;
+import org.jetbrains.annotations.Nullable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.server.common.SearchResults;
@@ -53,10 +54,11 @@ public class DefaultGroupController implements GroupController {
}
@Override
- public GroupsSearchRestResponse search(GroupsSearchRestRequest groupsSearchRestRequest, RestPage restPage) {
+ public GroupsSearchRestResponse search(GroupsSearchRestRequest groupsSearchRestRequest, @Nullable String excludedUserId, RestPage restPage) {
userSession.checkLoggedIn().checkIsSystemAdministrator();
try (DbSession dbSession = dbClient.openSession(false)) {
- GroupSearchRequest groupSearchRequest = new GroupSearchRequest(groupsSearchRestRequest.q(), groupsSearchRestRequest.managed(), restPage.pageIndex(), restPage.pageSize());
+ GroupSearchRequest groupSearchRequest = new GroupSearchRequest(groupsSearchRestRequest.q(), groupsSearchRestRequest.managed(), groupsSearchRestRequest.userId(),
+ excludedUserId, restPage.pageIndex(), restPage.pageSize());
SearchResults<GroupInformation> searchResults = groupService.search(dbSession, groupSearchRequest);
List<GroupRestResponse> groupRestResponses = toGroupRestResponses(searchResults);
return new GroupsSearchRestResponse(groupRestResponses, new PageRestResponse(restPage.pageIndex(), restPage.pageSize(), searchResults.total()));
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/GroupController.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/GroupController.java
index 666ba5e049e..f6f6a149679 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/GroupController.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/controller/GroupController.java
@@ -22,7 +22,11 @@ package org.sonar.server.v2.api.group.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.extensions.Extension;
+import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
+import javax.annotation.Nullable;
import org.sonar.server.v2.api.group.request.GroupCreateRestRequest;
import org.sonar.server.v2.api.group.request.GroupUpdateRestRequest;
import org.sonar.server.v2.api.group.request.GroupsSearchRestRequest;
@@ -39,6 +43,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@@ -57,6 +62,8 @@ public interface GroupController {
""")
GroupsSearchRestResponse search(
@Valid @ParameterObject GroupsSearchRestRequest groupsSearchRestRequest,
+ @RequestParam(name = "userId!") @Nullable @Schema(description = "Find groups without this user. Only available for system administrators.",
+ extensions = @Extension(properties = {@ExtensionProperty(name = "internal", value = "true")}), hidden = true) String excludedUserId,
@Valid @ParameterObject RestPage restPage);
@GetMapping(path = "/{id}")
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/request/GroupsSearchRestRequest.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/request/GroupsSearchRestRequest.java
index ab704c8112b..d829f29716b 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/request/GroupsSearchRestRequest.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/group/request/GroupsSearchRestRequest.java
@@ -19,6 +19,8 @@
*/
package org.sonar.server.v2.api.group.request;
+import io.swagger.v3.oas.annotations.extensions.Extension;
+import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.annotation.Nullable;
@@ -30,7 +32,12 @@ public record GroupsSearchRestRequest(
@Nullable
@Schema(description = "Filter on name.\n"
+ "This parameter performs a partial match (contains), it is case insensitive.")
- String q
+ String q,
+
+ @Nullable
+ @Schema(description = "Filter groups containing the user. Only available for system administrators. Using != operator will search for groups without the user.",
+ extensions = @Extension(properties = {@ExtensionProperty(name = "internal", value = "true")}))
+ String userId
) {
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGenerator.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGenerator.java
index 8cf5bc05bb1..a158f205091 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGenerator.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGenerator.java
@@ -64,7 +64,7 @@ public class UsersSearchRestResponseGenerator implements UsersSearchResponseGene
String login = userDto.getLogin();
String name = userDto.getName();
if (!userSession.isLoggedIn()) {
- return new UserRestResponseForAnonymousUsers(id, login, name);
+ return new UserRestResponseForAnonymousUsers(login, name);
}
String avatar = userInformation.avatar().orElse(null);
@@ -95,7 +95,7 @@ public class UsersSearchRestResponseGenerator implements UsersSearchResponseGene
slLastConnectionDate,
scmAccounts);
}
- return new UserRestResponseForLoggedInUsers(id, login, name, email, active, local, externalIdentityProvider, avatar);
+ return new UserRestResponseForLoggedInUsers(login, name, active, avatar);
}
private static String toDateTime(@Nullable Long dateTimeMs) {
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForAnonymousUsers.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForAnonymousUsers.java
index 71c344b814b..c6d787be217 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForAnonymousUsers.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForAnonymousUsers.java
@@ -20,7 +20,6 @@
package org.sonar.server.v2.api.user.response;
public record UserRestResponseForAnonymousUsers(
- String id,
String login,
String name
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForLoggedInUsers.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForLoggedInUsers.java
index 25900316432..4b84fbdd0de 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForLoggedInUsers.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/api/user/response/UserRestResponseForLoggedInUsers.java
@@ -22,18 +22,11 @@ package org.sonar.server.v2.api.user.response;
import javax.annotation.Nullable;
public record UserRestResponseForLoggedInUsers(
- String id,
String login,
String name,
@Nullable
- String email,
- @Nullable
Boolean active,
@Nullable
- Boolean local,
- @Nullable
- String externalProvider,
- @Nullable
String avatar
) implements UserRestResponse {
diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/group/controller/DefaultGroupControllerTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/group/controller/DefaultGroupControllerTest.java
index c9d7070816d..2b6fec3c337 100644
--- a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/group/controller/DefaultGroupControllerTest.java
+++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/group/controller/DefaultGroupControllerTest.java
@@ -412,6 +412,8 @@ public class DefaultGroupControllerTest {
assertThat(requestCaptor.getValue().page()).hasToString(DEFAULT_PAGE_INDEX);
assertThat(requestCaptor.getValue().managed()).isNull();
assertThat(requestCaptor.getValue().query()).isNull();
+ assertThat(requestCaptor.getValue().userUuid()).isNull();
+ assertThat(requestCaptor.getValue().excludedUserUuid()).isNull();
}
@Test
@@ -422,6 +424,8 @@ public class DefaultGroupControllerTest {
mockMvc.perform(get(GROUPS_ENDPOINT)
.param("managed", "true")
.param("q", "q")
+ .param("userId", "userId")
+ .param("userId!", "excludedUserId")
.param("pageSize", "100")
.param("pageIndex", "2"))
.andExpect(status().isOk());
@@ -432,6 +436,8 @@ public class DefaultGroupControllerTest {
assertThat(requestCaptor.getValue().page()).isEqualTo(2);
assertThat(requestCaptor.getValue().managed()).isTrue();
assertThat(requestCaptor.getValue().query()).isEqualTo("q");
+ assertThat(requestCaptor.getValue().userUuid()).isEqualTo("userId");
+ assertThat(requestCaptor.getValue().excludedUserUuid()).isEqualTo("excludedUserId");
}
@Test
diff --git a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGeneratorTest.java b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGeneratorTest.java
index 0780e7435ab..bda36f5e806 100644
--- a/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGeneratorTest.java
+++ b/server/sonar-webserver-webapi-v2/src/test/java/org/sonar/server/v2/api/user/converter/UsersSearchRestResponseGeneratorTest.java
@@ -121,13 +121,9 @@ public class UsersSearchRestResponseGeneratorTest {
private static UserRestResponseForLoggedInUsers buildExpectedResponseForUser(UserInformation userInformation) {
UserDto userDto = userInformation.userDto();
return new UserRestResponseForLoggedInUsers(
- userDto.getUuid(),
userDto.getLogin(),
userDto.getName(),
- userDto.getEmail(),
userDto.isActive(),
- userDto.isLocal(),
- userDto.getExternalIdentityProvider(),
userInformation.avatar().orElse(null)
);
}
@@ -150,7 +146,6 @@ public class UsersSearchRestResponseGeneratorTest {
private static UserRestResponseForAnonymousUsers buildExpectedResponseForAnonymous(UserInformation userInformation) {
UserDto userDto = userInformation.userDto();
return new UserRestResponseForAnonymousUsers(
- userDto.getUuid(),
userDto.getLogin(),
userDto.getName()
);
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
index 5b0d652caf6..811b8c10f54 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java
@@ -73,7 +73,7 @@ public class SearchAction implements UserGroupsWsAction {
public void define(NewController context) {
WebService.NewAction action = context.createAction("search")
.setDescription("Search for user groups.<br>" +
- "Requires the following permission: 'Administer System'.")
+ "Requires the following permission: 'Administer System'.")
.setHandler(this)
.setResponseExample(getClass().getResource("search-example.json"))
.setSince("5.2")
@@ -107,7 +107,8 @@ public class SearchAction implements UserGroupsWsAction {
try (DbSession dbSession = dbClient.openSession(false)) {
userSession.checkLoggedIn().checkIsSystemAdministrator();
- GroupSearchRequest groupSearchRequest = new GroupSearchRequest(request.param(Param.TEXT_QUERY), request.paramAsBoolean(MANAGED_PARAM), page, pageSize);
+ GroupSearchRequest groupSearchRequest = new GroupSearchRequest(request.param(Param.TEXT_QUERY), request.paramAsBoolean(MANAGED_PARAM), null, null,
+ page, pageSize);
SearchResults<GroupInformation> searchResults = groupService.search(dbSession, groupSearchRequest);
Set<String> groupUuids = extractGroupUuids(searchResults.searchResults());
@@ -136,7 +137,7 @@ public class SearchAction implements UserGroupsWsAction {
}
private static SearchWsResponse buildResponse(List<GroupInformation> groups, Map<String, Integer> userCountByGroup,
- Set<String> fields, Paging paging) {
+ Set<String> fields, Paging paging) {
SearchWsResponse.Builder responseBuilder = SearchWsResponse.newBuilder();
groups.forEach(group -> responseBuilder
.addGroups(toWsGroup(group.groupDto(), userCountByGroup.get(group.groupDto().getName()), group.isManaged(), fields, group.isDefault())));