diff options
author | Jacek Poreda <jacek.poreda@sonarsource.com> | 2024-09-17 14:59:33 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-09-20 20:02:37 +0000 |
commit | 747d4ede9457dcf3dd0e89d080913f3e24396361 (patch) | |
tree | 7f09834ed423c2a2acaa50a00096d3cc6d6c2e1b /server/sonar-webserver-webapi | |
parent | 300226052a9c81c3246472e645087580b201824e (diff) | |
download | sonarqube-747d4ede9457dcf3dd0e89d080913f3e24396361.tar.gz sonarqube-747d4ede9457dcf3dd0e89d080913f3e24396361.zip |
SONAR-23070 Fix SSF-635
Diffstat (limited to 'server/sonar-webserver-webapi')
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; + } } |