aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorJacek Poreda <jacek.poreda@sonarsource.com>2024-09-17 14:59:33 +0200
committersonartech <sonartech@sonarsource.com>2024-09-20 20:02:37 +0000
commit747d4ede9457dcf3dd0e89d080913f3e24396361 (patch)
tree7f09834ed423c2a2acaa50a00096d3cc6d6c2e1b /server/sonar-webserver-webapi
parent300226052a9c81c3246472e645087580b201824e (diff)
downloadsonarqube-747d4ede9457dcf3dd0e89d080913f3e24396361.tar.gz
sonarqube-747d4ede9457dcf3dd0e89d080913f3e24396361.zip
SONAR-23070 Fix SSF-635
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java48
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java20
2 files changed, 42 insertions, 26 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
index f7744ed7dc4..ca96953776b 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
@@ -41,6 +41,7 @@ import org.sonar.api.resources.Qualifiers;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
import org.sonar.core.platform.EditionProvider.Edition;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.DbClient;
@@ -130,12 +131,12 @@ public class SearchProjectsActionIT {
@DataProvider
public static Object[][] rating_metric_keys() {
- return new Object[][]{{SQALE_RATING_KEY}, {RELIABILITY_RATING_KEY}, {SECURITY_RATING_KEY}};
+ return new Object[][] {{SQALE_RATING_KEY}, {RELIABILITY_RATING_KEY}, {SECURITY_RATING_KEY}};
}
@DataProvider
public static Object[][] software_quality_rating_metric_keys() {
- return new Object[][]{{SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
+ return new Object[][] {{SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
{SOFTWARE_QUALITY_SECURITY_RATING_KEY}};
}
@@ -149,12 +150,12 @@ public class SearchProjectsActionIT {
@DataProvider
public static Object[][] new_rating_metric_keys() {
- return new Object[][]{{NEW_MAINTAINABILITY_RATING_KEY}, {NEW_RELIABILITY_RATING_KEY}, {NEW_SECURITY_RATING_KEY}};
+ return new Object[][] {{NEW_MAINTAINABILITY_RATING_KEY}, {NEW_RELIABILITY_RATING_KEY}, {NEW_SECURITY_RATING_KEY}};
}
@DataProvider
public static Object[][] new_software_quality_rating_metric_keys() {
- return new Object[][]{{NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
+ return new Object[][] {{NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
{NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY}};
}
@@ -168,17 +169,17 @@ public class SearchProjectsActionIT {
@DataProvider
public static Object[][] component_qualifiers_for_valid_editions() {
- return new Object[][]{
- {new String[]{Qualifiers.PROJECT}, Edition.COMMUNITY},
- {new String[]{Qualifiers.APP, Qualifiers.PROJECT}, Edition.DEVELOPER},
- {new String[]{Qualifiers.APP, Qualifiers.PROJECT}, Edition.ENTERPRISE},
- {new String[]{Qualifiers.APP, Qualifiers.PROJECT}, Edition.DATACENTER},
+ return new Object[][] {
+ {new String[] {Qualifiers.PROJECT}, Edition.COMMUNITY},
+ {new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.DEVELOPER},
+ {new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.ENTERPRISE},
+ {new String[] {Qualifiers.APP, Qualifiers.PROJECT}, Edition.DATACENTER},
};
}
@DataProvider
public static Object[][] community_or_developer_edition() {
- return new Object[][]{
+ return new Object[][] {
{Edition.COMMUNITY},
{Edition.DEVELOPER},
};
@@ -186,25 +187,25 @@ public class SearchProjectsActionIT {
@DataProvider
public static Object[][] enterprise_or_datacenter_edition() {
- return new Object[][]{
+ return new Object[][] {
{Edition.ENTERPRISE},
{Edition.DATACENTER},
};
}
- private DbClient dbClient = db.getDbClient();
- private DbSession dbSession = db.getSession();
+ private final DbClient dbClient = db.getDbClient();
+ private final DbSession dbSession = db.getSession();
- private PlatformEditionProvider editionProviderMock = mock(PlatformEditionProvider.class);
- private PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, new ProjectMeasuresIndexer(dbClient,
+ private final PlatformEditionProvider editionProviderMock = mock(PlatformEditionProvider.class);
+ private final PermissionIndexerTester authorizationIndexerTester = new PermissionIndexerTester(es, new ProjectMeasuresIndexer(dbClient,
es.client()));
- private ProjectMeasuresIndex index = new ProjectMeasuresIndex(es.client(), new WebAuthorizationTypeSupport(userSession),
+ private final ProjectMeasuresIndex index = new ProjectMeasuresIndex(es.client(), new WebAuthorizationTypeSupport(userSession),
System2.INSTANCE);
- private ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(db.getDbClient(), es.client());
+ private final ProjectMeasuresIndexer projectMeasuresIndexer = new ProjectMeasuresIndexer(db.getDbClient(), es.client());
- private WsActionTester ws = new WsActionTester(new SearchProjectsAction(dbClient, index, userSession, editionProviderMock));
+ private final WsActionTester ws = new WsActionTester(new SearchProjectsAction(dbClient, index, userSession, editionProviderMock));
- private RequestBuilder request = SearchProjectsRequest.builder();
+ private final RequestBuilder request = SearchProjectsRequest.builder();
@Test
public void verify_definition() {
@@ -260,8 +261,7 @@ public class SearchProjectsActionIT {
Param facets = def.param("facets");
assertThat(facets.defaultValue()).isNull();
- assertThat(facets.possibleValues()).containsOnly("ncloc", "duplicated_lines_density", "coverage", "sqale_rating", "reliability_rating"
- , "security_rating", "alert_status",
+ assertThat(facets.possibleValues()).containsOnly("ncloc", "duplicated_lines_density", "coverage", "sqale_rating", "reliability_rating", "security_rating", "alert_status",
"languages", "tags", "qualifier", "new_reliability_rating", "new_security_rating", "new_maintainability_rating", "new_coverage",
"new_duplicated_lines_density", "new_lines",
"security_review_rating", "security_hotspots_reviewed", "new_security_hotspots_reviewed", "new_security_review_rating",
@@ -1370,12 +1370,14 @@ public class SearchProjectsActionIT {
@Test
public void return_visibility_flag() {
userSession.logIn();
- ProjectDto privateProject = db.components().insertPublicProject(componentDto -> componentDto.setName("proj_A")).getProjectDto();
+ ProjectDto privateProject = db.components().insertPrivateProject(componentDto -> componentDto.setName("proj_A")).getProjectDto();
authorizationIndexerTester.allowOnlyAnyone(privateProject);
- ProjectDto publicProject = db.components().insertPrivateProject(componentDto -> componentDto.setName("proj_B")).getProjectDto();
+ ProjectDto publicProject = db.components().insertPublicProject(componentDto -> componentDto.setName("proj_B")).getProjectDto();
authorizationIndexerTester.allowOnlyAnyone(publicProject);
index();
+ userSession.addProjectPermission(UserRole.USER, privateProject);
+
SearchProjectsWsResponse result = call(request);
assertThat(result.getComponentsList()).extracting(Component::getKey, Component::getVisibility)
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java
index f6b51f76de4..6d4c8ccb05e 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java
@@ -46,6 +46,7 @@ import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
+import org.sonar.api.web.UserRole;
import org.sonar.core.platform.EditionProvider.Edition;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.db.DbClient;
@@ -55,6 +56,7 @@ import org.sonar.db.component.SnapshotDto;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.property.PropertyQuery;
+import org.sonar.db.user.TokenType;
import org.sonar.server.component.ws.FilterParser.Criterion;
import org.sonar.server.component.ws.SearchProjectsAction.SearchResults.SearchResultsBuilder;
import org.sonar.server.es.Facets;
@@ -63,6 +65,7 @@ import org.sonar.server.es.SearchOptions;
import org.sonar.server.measure.index.ProjectMeasuresIndex;
import org.sonar.server.measure.index.ProjectMeasuresQuery;
import org.sonar.server.project.Visibility;
+import org.sonar.server.user.TokenUserSession;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Common;
import org.sonarqube.ws.Components.Component;
@@ -236,12 +239,15 @@ public class SearchProjectsAction implements ComponentsWsAction {
ProjectMeasuresQueryValidator.validate(query);
SearchIdResult<String> esResults = index.search(query, new SearchOptions()
- .addFacets(request.getFacets())
+ // skip facets for project token authorization, avoid exposing unauthorized projects count
+ .addFacets(isProjectAnalysisToken() ? emptyList() : request.getFacets())
.setPage(request.getPage(), request.getPageSize()));
List<String> projectUuids = esResults.getUuids();
Ordering<ProjectDto> ordering = Ordering.explicit(projectUuids).onResultOf(ProjectDto::getUuid);
List<ProjectDto> projects = ordering.immutableSortedCopy(dbClient.projectDao().selectByUuids(dbSession, new HashSet<>(projectUuids)));
+ projects = userSession.keepAuthorizedEntities(UserRole.USER, projects);
+
Map<String, BranchDto> mainBranchByUuid = dbClient.branchDao().selectMainBranchesByProjectUuids(dbSession, projectUuids)
.stream()
.collect(Collectors.toMap(BranchDto::getUuid, b -> b));
@@ -281,7 +287,7 @@ public class SearchProjectsAction implements ComponentsWsAction {
private Set<String> getQualifiersFromEdition() {
Optional<Edition> edition = editionProvider.get();
- if (!edition.isPresent()) {
+ if (edition.isEmpty()) {
return Sets.newHashSet(Qualifiers.PROJECT);
}
@@ -367,7 +373,8 @@ public class SearchProjectsAction implements ComponentsWsAction {
.map(response -> response.setPaging(Common.Paging.newBuilder()
.setPageIndex(request.getPage())
.setPageSize(request.getPageSize())
- .setTotal(searchResults.total)))
+ // skip total for project token authorization, avoid exposing unauthorized projects count
+ .setTotal(isProjectAnalysisToken() ? searchResults.projects.size() : searchResults.total)))
.map(response -> {
searchResults.projects.stream()
.map(dbToWsComponent)
@@ -690,4 +697,11 @@ public class SearchProjectsAction implements ComponentsWsAction {
return new SearchProjectsRequest(this);
}
}
+
+ private boolean isProjectAnalysisToken() {
+ if (userSession instanceof TokenUserSession tokenUserSession) {
+ return TokenType.PROJECT_ANALYSIS_TOKEN.equals(tokenUserSession.getTokenType());
+ }
+ return false;
+ }
}