From 2232f4785c4f1a373db310164bc23c280d3ad007 Mon Sep 17 00:00:00 2001 From: Jacek Date: Tue, 30 Nov 2021 11:59:21 +0100 Subject: [PATCH] SONAR-15702 Return '403' in case WEB API called without access to all application's projects - api/measures/component_tree - api/measures/search_history - api/qualitygates/application_status - api/applications/show_leak - api/project_analysis/search --- .../server/user/AbstractUserSession.java | 22 +++++++++- .../server/user/ThreadLocalUserSession.java | 11 +++++ .../org/sonar/server/user/UserSession.java | 8 ++++ .../user/ThreadLocalUserSessionTest.java | 44 +++++++++++++++++++ .../sonar/server/tester/UserSessionRule.java | 11 +++++ .../measure/ws/ComponentTreeAction.java | 9 +++- .../measure/ws/SearchHistoryAction.java | 5 +++ .../projectanalysis/ws/SearchAction.java | 3 ++ .../measure/ws/ComponentTreeActionTest.java | 33 +++++++++++--- .../measure/ws/SearchHistoryActionTest.java | 35 ++++++++++++--- .../projectanalysis/ws/SearchActionTest.java | 36 +++++++++++---- 11 files changed, 193 insertions(+), 24 deletions(-) diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java index 3d36461a0e5..c9902161477 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java @@ -36,6 +36,7 @@ import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import static org.apache.commons.lang.StringUtils.defaultString; +import static org.sonar.api.resources.Qualifiers.APP; import static org.sonar.server.user.UserSession.IdentityProvider.SONARQUBE; public abstract class AbstractUserSession implements UserSession { @@ -109,7 +110,16 @@ public abstract class AbstractUserSession implements UserSession { if (isRoot()) { return true; } - return hasChildProjectsPermission(permission, component.uuid()); + String applicationUuid = defaultString(component.getMainBranchProjectUuid(), component.projectUuid()); + return hasChildProjectsPermission(permission, applicationUuid); + } + + @Override + public final boolean hasChildProjectsPermission(String permission, ProjectDto project) { + if (isRoot()) { + return true; + } + return hasChildProjectsPermission(permission, project.getUuid()); } @Override @@ -208,12 +218,20 @@ public abstract class AbstractUserSession implements UserSession { @Override public UserSession checkChildProjectsPermission(String projectPermission, ComponentDto component) { - if (isRoot() || !component.qualifier().equals(Qualifiers.APP) || hasChildProjectsPermission(projectPermission, component.uuid())) { + if (isRoot() || !APP.equals(component.qualifier()) || hasChildProjectsPermission(projectPermission, component)) { return this; } throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE); + } + + @Override + public UserSession checkChildProjectsPermission(String projectPermission, ProjectDto application) { + if (isRoot() || !APP.equals(application.getQualifier()) || hasChildProjectsPermission(projectPermission, application)) { + return this; + } + throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE); } @Override diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java index 8102efd755f..2584b0ac0c2 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java @@ -150,6 +150,12 @@ public class ThreadLocalUserSession implements UserSession { return this; } + @Override + public UserSession checkChildProjectsPermission(String projectPermission, ProjectDto application) { + get().checkChildProjectsPermission(projectPermission, application); + return this; + } + @Override public UserSession checkComponentUuidPermission(String permission, String componentUuid) { get().checkComponentUuidPermission(permission, componentUuid); @@ -182,6 +188,11 @@ public class ThreadLocalUserSession implements UserSession { return get().hasChildProjectsPermission(permission, component); } + @Override + public boolean hasChildProjectsPermission(String permission, ProjectDto project) { + return get().hasChildProjectsPermission(permission, project); + } + @Override public boolean hasComponentUuidPermission(String permission, String componentUuid) { return get().hasComponentUuidPermission(permission, componentUuid); diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java index fd6e8f71556..157042f8f6c 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java @@ -197,6 +197,8 @@ public interface UserSession { boolean hasChildProjectsPermission(String permission, ComponentDto component); + boolean hasChildProjectsPermission(String permission, ProjectDto component); + /** * Using {@link #hasComponentPermission(String, ComponentDto)} is recommended * because it does not have to load project if the referenced component @@ -236,6 +238,12 @@ public interface UserSession { */ UserSession checkChildProjectsPermission(String projectPermission, ComponentDto project); + /** + * Ensures that {@link #hasChildProjectsPermission(String, ProjectDto)} is {@code true} + * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkChildProjectsPermission(String projectPermission, ProjectDto application); + /** * Ensures that {@link #hasComponentUuidPermission(String, String)} is {@code true}, * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java index c9ccb3c984d..81abd518045 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ThreadLocalUserSessionTest.java @@ -22,9 +22,12 @@ package org.sonar.server.user; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.sonar.api.resources.Qualifiers; import org.sonar.db.component.ComponentDto; +import org.sonar.db.project.ProjectDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.GroupTesting; +import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.tester.AnonymousMockUserSession; import org.sonar.server.tester.MockUserSession; @@ -68,6 +71,7 @@ public class ThreadLocalUserSessionTest { assertThat(threadLocalUserSession.shouldResetPassword()).isTrue(); assertThat(threadLocalUserSession.getGroups()).extracting(GroupDto::getUuid).containsOnly(group.getUuid()); assertThat(threadLocalUserSession.hasChildProjectsPermission(USER, new ComponentDto())).isFalse(); + assertThat(threadLocalUserSession.hasChildProjectsPermission(USER, new ProjectDto())).isFalse(); } @Test @@ -89,4 +93,44 @@ public class ThreadLocalUserSessionTest { .isInstanceOf(UnauthorizedException.class); } + @Test + public void throw_ForbiddenException_when_no_access_to_applications_projects() { + GroupDto group = GroupTesting.newGroupDto(); + MockUserSession expected = new MockUserSession("karadoc") + .setUuid("karadoc-uuid") + .setResetPassword(true) + .setLastSonarlintConnectionDate(1000L) + .setGroups(group); + threadLocalUserSession.set(expected); + + ComponentDto componentDto = new ComponentDto().setQualifier(Qualifiers.APP).setMainBranchProjectUuid("component-uuid"); + ProjectDto projectDto = new ProjectDto().setQualifier(Qualifiers.APP).setUuid("project-uuid"); + assertThatThrownBy(() -> threadLocalUserSession.checkChildProjectsPermission(USER, componentDto)) + .isInstanceOf(ForbiddenException.class); + assertThatThrownBy(() -> threadLocalUserSession.checkChildProjectsPermission(USER, projectDto)) + .isInstanceOf(ForbiddenException.class); + } + + @Test + public void checkChildProjectsPermission_gets_session_when_user_has_access_to_applications_projects() { + GroupDto group = GroupTesting.newGroupDto(); + MockUserSession expected = new MockUserSession("karadoc") + .setUuid("karadoc-uuid") + .setResetPassword(true) + .setLastSonarlintConnectionDate(1000L) + .setGroups(group); + + ProjectDto subProjectDto = new ProjectDto().setQualifier(Qualifiers.PROJECT).setUuid("subproject-uuid"); + ComponentDto applicationAsComponentDto = new ComponentDto().setQualifier(Qualifiers.APP).setUuid("application-component-uuid").setProjectUuid("application-project-uuid"); + ProjectDto applicationAsProjectDto = new ProjectDto().setQualifier(Qualifiers.APP).setUuid("application-project-uuid"); + + expected.registerProjects(subProjectDto); + expected.registerApplication(applicationAsProjectDto, subProjectDto); + expected.registerComponents(applicationAsComponentDto); + threadLocalUserSession.set(expected); + + assertThat(threadLocalUserSession.checkChildProjectsPermission(USER, applicationAsComponentDto)).isEqualTo(threadLocalUserSession); + assertThat(threadLocalUserSession.checkChildProjectsPermission(USER, applicationAsProjectDto)).isEqualTo(threadLocalUserSession); + } + } diff --git a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java index 4b33d0ff77c..c343ae92d19 100644 --- a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java +++ b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java @@ -261,6 +261,11 @@ public class UserSessionRule implements TestRule, UserSession { return currentUserSession.hasChildProjectsPermission(permission, component); } + @Override + public boolean hasChildProjectsPermission(String permission, ProjectDto component) { + return currentUserSession.hasChildProjectsPermission(permission, component); + } + @Override public boolean hasComponentUuidPermission(String permission, String componentUuid) { return currentUserSession.hasComponentUuidPermission(permission, componentUuid); @@ -370,6 +375,12 @@ public class UserSessionRule implements TestRule, UserSession { return this; } + @Override + public UserSession checkChildProjectsPermission(String projectPermission, ProjectDto application) { + currentUserSession.checkChildProjectsPermission(projectPermission, application); + return this; + } + @Override public UserSession checkComponentUuidPermission(String permission, String componentUuid) { currentUserSession.checkComponentUuidPermission(permission, componentUuid); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java index 19463501303..66fbe2ce9d7 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java @@ -46,6 +46,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.ResourceTypes; +import org.sonar.api.resources.Scopes; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -105,8 +106,8 @@ import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriod.snapshotToWsPeri import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001; -import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter; +import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext; import static org.sonar.server.ws.WsUtils.writeProtobuf; /** @@ -402,7 +403,7 @@ public class ComponentTreeAction implements MeasuresWsAction { ComponentDto baseComponent = loadComponent(dbSession, wsRequest); checkPermissions(baseComponent); Optional baseSnapshot = dbClient.snapshotDao().selectLastAnalysisByRootComponentUuid(dbSession, baseComponent.projectUuid()); - if (!baseSnapshot.isPresent()) { + if (baseSnapshot.isEmpty()) { return ComponentTreeData.builder() .setBaseComponent(baseComponent) .build(); @@ -625,6 +626,10 @@ public class ComponentTreeAction implements MeasuresWsAction { private void checkPermissions(ComponentDto baseComponent) { userSession.checkComponentPermission(UserRole.USER, baseComponent); + + if (Scopes.PROJECT.equals(baseComponent.scope()) && Qualifiers.APP.equals(baseComponent.qualifier())) { + userSession.checkChildProjectsPermission(UserRole.USER, baseComponent); + } } public static boolean isFileComponent(@Nonnull ComponentDto input) { diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java index 44ecf17aec5..9cca3a1a218 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/SearchHistoryAction.java @@ -27,6 +27,8 @@ import java.util.function.Function; import java.util.stream.Stream; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -166,6 +168,9 @@ public class SearchHistoryAction implements MeasuresWsAction { private ComponentDto searchComponent(SearchHistoryRequest request, DbSession dbSession) { ComponentDto component = loadComponent(dbSession, request); userSession.checkComponentPermission(UserRole.USER, component); + if (Scopes.PROJECT.equals(component.scope()) && Qualifiers.APP.equals(component.qualifier())) { + userSession.checkChildProjectsPermission(UserRole.USER, component); + } return component; } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectanalysis/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectanalysis/ws/SearchAction.java index 706fa91a7f0..745a50aa694 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectanalysis/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/projectanalysis/ws/SearchAction.java @@ -177,6 +177,9 @@ public class SearchAction implements ProjectAnalysesWsAction { private void checkPermission(ComponentDto project) { userSession.checkComponentPermission(UserRole.USER, project); + if (Scopes.PROJECT.equals(project.scope()) && Qualifiers.APP.equals(project.qualifier())) { + userSession.checkChildProjectsPermission(UserRole.USER, project); + } } private void addProject(SearchData.Builder data) { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java index 8f467a74fc4..b25b1751ef7 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java @@ -70,6 +70,7 @@ import static org.sonar.api.resources.Qualifiers.UNIT_TEST_FILE; import static org.sonar.api.server.ws.WebService.Param.SORT; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.BranchType.PULL_REQUEST; +import static org.sonar.db.component.ComponentDbTester.toProjectDto; import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newProjectCopy; @@ -833,12 +834,32 @@ public class ComponentTreeActionTest { ComponentDto project = db.components().insertPrivateProject(); db.components().insertSnapshot(project); - assertThatThrownBy(() -> { - ws.newRequest() - .setParam(PARAM_COMPONENT, project.getKey()) - .setParam(PARAM_METRIC_KEYS, "ncloc") - .executeProtobuf(ComponentTreeWsResponse.class); - }) + var request = ws.newRequest() + .setParam(PARAM_COMPONENT, project.getKey()) + .setParam(PARAM_METRIC_KEYS, "ncloc"); + assertThatThrownBy(() -> request.executeProtobuf(ComponentTreeWsResponse.class)) + .isInstanceOf(ForbiddenException.class); + } + + @Test + public void fail_when_app_with_insufficient_privileges_for_projects() { + userSession.logIn(); + ComponentDto app = db.components().insertPrivateApplication(); + ComponentDto project1 = db.components().insertPrivateProject(); + ComponentDto project2 = db.components().insertPrivateProject(); + db.components().insertSnapshot(app); + + userSession.registerApplication( + toProjectDto(app, 1L), + toProjectDto(project1, 1L), + toProjectDto(project2, 1L)); + + userSession.addProjectPermission(UserRole.USER, app, project1); + + var request = ws.newRequest() + .setParam(PARAM_COMPONENT, app.getKey()) + .setParam(PARAM_METRIC_KEYS, "ncloc"); + assertThatThrownBy(() -> request.executeProtobuf(ComponentTreeWsResponse.class)) .isInstanceOf(ForbiddenException.class); } diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java index 0375a2c9f0d..be355c219f4 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/ws/SearchHistoryActionTest.java @@ -60,6 +60,7 @@ import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.BranchType.PULL_REQUEST; +import static org.sonar.db.component.ComponentDbTester.toProjectDto; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED; @@ -347,8 +348,8 @@ public class SearchHistoryActionTest { .setParam(PARAM_COMPONENT, branch.getDbKey()) .setParam(PARAM_METRICS, "ncloc") .execute()) - .isInstanceOf(NotFoundException.class) - .hasMessageContaining(format("Component key '%s' not found", branch.getDbKey())); + .isInstanceOf(NotFoundException.class) + .hasMessageContaining(format("Component key '%s' not found", branch.getDbKey())); } @Test @@ -375,6 +376,28 @@ public class SearchHistoryActionTest { .isInstanceOf(ForbiddenException.class); } + @Test + public void fail_if_not_enough_permissions_for_application() { + ComponentDto application = db.components().insertPrivateApplication(); + ComponentDto project1 = db.components().insertPrivateProject(); + ComponentDto project2 = db.components().insertPrivateProject(); + + userSession.logIn() + .registerApplication( + toProjectDto(application, 1L), + toProjectDto(project1, 1L), + toProjectDto(project2, 1L)) + .addProjectPermission(UserRole.USER, application, project1); + + SearchHistoryRequest request = SearchHistoryRequest.builder() + .setComponent(application.getDbKey()) + .setMetrics(singletonList(complexityMetric.getKey())) + .build(); + + assertThatThrownBy(() -> call(request)) + .isInstanceOf(ForbiddenException.class); + } + @Test public void fail_if_unknown_component() { SearchHistoryRequest request = SearchHistoryRequest.builder() @@ -396,8 +419,8 @@ public class SearchHistoryActionTest { .setParam(PARAM_COMPONENT, "file-key") .setParam(PARAM_METRICS, "ncloc") .execute()) - .isInstanceOf(NotFoundException.class) - .hasMessageContaining("Component key 'file-key' not found"); + .isInstanceOf(NotFoundException.class) + .hasMessageContaining("Component key 'file-key' not found"); } @Test @@ -412,8 +435,8 @@ public class SearchHistoryActionTest { .setParam(PARAM_BRANCH, "another_branch") .setParam(PARAM_METRICS, "ncloc") .execute()) - .isInstanceOf(NotFoundException.class) - .hasMessageContaining(String.format("Component '%s' on branch '%s' not found", file.getKey(), "another_branch")); + .isInstanceOf(NotFoundException.class) + .hasMessageContaining(String.format("Component '%s' on branch '%s' not found", file.getKey(), "another_branch")); } @Test diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/projectanalysis/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/projectanalysis/ws/SearchActionTest.java index d2b6938ac08..25b6bb4a82f 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/projectanalysis/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/projectanalysis/ws/SearchActionTest.java @@ -72,6 +72,7 @@ import static org.sonar.api.utils.DateUtils.formatDate; import static org.sonar.api.utils.DateUtils.formatDateTime; import static org.sonar.api.utils.DateUtils.parseDateTime; import static org.sonar.db.component.BranchType.BRANCH; +import static org.sonar.db.component.ComponentDbTester.toProjectDto; import static org.sonar.db.component.ComponentTesting.newBranchDto; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.SnapshotTesting.newAnalysis; @@ -155,7 +156,8 @@ public class SearchActionTest { db.events().insertEvent(newEvent(a1).setUuid("AXt91FkXy_c4CIP4ds6A") .setName("Failed") .setCategory(QUALITY_GATE.getLabel()) - .setDescription("Coverage on New Code < 85, Reliability Rating > 4, Maintainability Rating on New Code > 1, Reliability Rating on New Code > 1, Security Rating on New Code > 1, Duplicated Lines (%) on New Code > 3")); + .setDescription( + "Coverage on New Code < 85, Reliability Rating > 4, Maintainability Rating on New Code > 1, Reliability Rating on New Code > 1, Security Rating on New Code > 1, Duplicated Lines (%) on New Code > 3")); db.events().insertEvent(newEvent(a1).setUuid("AXx_QFJ6Wa8wkfuJ6r5P") .setName("6.3").setCategory(VERSION.getLabel())); db.events().insertEvent(newEvent(a2).setUuid("E21") @@ -234,7 +236,7 @@ public class SearchActionTest { @Test public void return_analyses_of_application() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); SnapshotDto secondAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(2_000_000L)); SnapshotDto thirdAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(3_000_000L)); @@ -253,7 +255,7 @@ public class SearchActionTest { @Test public void return_definition_change_events_on_application_analyses() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent(newEvent(firstAnalysis).setName("").setUuid("E11").setCategory(DEFINITION_CHANGE.getLabel())); EventComponentChangeDto changeDto1 = generateEventComponentChange(event, ADDED, "My project", "app1", "master", uuidFactoryFast.create()); @@ -278,7 +280,7 @@ public class SearchActionTest { @UseDataProvider("changedBranches") public void application_definition_change_with_branch(@Nullable String oldBranch, @Nullable String newBranch) { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent(newEvent(firstAnalysis).setName("").setUuid("E11").setCategory(DEFINITION_CHANGE.getLabel())); EventComponentChangeDto changeDto1 = generateEventComponentChange(event, REMOVED, "My project", "app1", oldBranch, uuidFactoryFast.create()); @@ -300,7 +302,7 @@ public class SearchActionTest { @Test public void incorrect_eventcomponentchange_two_identical_changes_added_on_same_project() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent(newEvent(firstAnalysis).setName("").setUuid("E11").setCategory(DEFINITION_CHANGE.getLabel())); EventComponentChangeDto changeDto1 = generateEventComponentChange(event, ADDED, "My project", "app1", "master", uuidFactoryFast.create()); @@ -329,7 +331,7 @@ public class SearchActionTest { @Test public void incorrect_eventcomponentchange_incorrect_category() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent(newEvent(firstAnalysis).setName("").setUuid("E11").setCategory(DEFINITION_CHANGE.getLabel())); EventComponentChangeDto changeDto1 = generateEventComponentChange(event, FAILED_QUALITY_GATE, "My project", "app1", "master", uuidFactoryFast.create()); @@ -355,7 +357,7 @@ public class SearchActionTest { @Test public void incorrect_eventcomponentchange_three_component_changes_on_same_project() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent(newEvent(firstAnalysis).setName("").setUuid("E11").setCategory(DEFINITION_CHANGE.getLabel())); EventComponentChangeDto changeDto1 = generateEventComponentChange(event, ADDED, "My project", "app1", "master", uuidFactoryFast.create()); @@ -386,7 +388,7 @@ public class SearchActionTest { @Test public void incorrect_quality_gate_information() { ComponentDto application = db.components().insertPublicApplication(); - userSession.registerComponents(application); + userSession.registerApplication(toProjectDto(application, 1L)); SnapshotDto firstAnalysis = db.components().insertSnapshot(newAnalysis(application).setCreatedAt(1_000_000L)); EventDto event = db.events().insertEvent( newEvent(firstAnalysis) @@ -639,6 +641,24 @@ public class SearchActionTest { .isInstanceOf(ForbiddenException.class); } + @Test + public void fail_if_not_enough_permissions_on_applications_projects() { + ComponentDto application = db.components().insertPrivateApplication(); + ComponentDto project1 = db.components().insertPrivateProject(); + ComponentDto project2 = db.components().insertPrivateProject(); + + userSession.logIn() + .registerApplication( + toProjectDto(application, 1L), + toProjectDto(project1, 1L), + toProjectDto(project2, 1L)) + .addProjectPermission(UserRole.USER, application, project1); + + var projectDbKey = application.getDbKey(); + assertThatThrownBy(() -> call(projectDbKey)) + .isInstanceOf(ForbiddenException.class); + } + @Test public void fail_if_project_does_not_exist() { assertThatThrownBy(() -> call("P1")) -- 2.39.5