From 0000edfd89ee6084a0cde4a08424b3bad346e69e Mon Sep 17 00:00:00 2001 From: Eric Hartmann Date: Tue, 12 Sep 2017 16:37:01 +0200 Subject: [PATCH] SONAR-9227 Forbid adding a notification on project without BROWSE permission --- .../server/notification/ws/AddAction.java | 12 ++-- .../server/notification/ws/AddActionTest.java | 55 ++++++++++++++++++- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java index 51685ce0c1f..65eab55e15a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java @@ -21,13 +21,13 @@ package org.sonar.server.notification.ws; import java.util.List; import java.util.Optional; -import javax.annotation.CheckForNull; import org.sonar.api.notifications.NotificationChannel; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; 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.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; @@ -124,8 +124,8 @@ public class AddAction implements NotificationsWsAction { try (DbSession dbSession = dbClient.openSession(false)) { checkPermissions(request); UserDto user = getUser(dbSession, request); - ComponentDto project = searchProject(dbSession, request); - notificationUpdater.add(dbSession, request.getChannel(), request.getType(), user, project); + Optional project = searchProject(dbSession, request); + notificationUpdater.add(dbSession, request.getChannel(), request.getType(), user, project.orElse(null)); dbSession.commit(); } } @@ -135,12 +135,12 @@ public class AddAction implements NotificationsWsAction { return checkFound(dbClient.userDao().selectByLogin(dbSession, login), "User '%s' not found", login); } - @CheckForNull - private ComponentDto searchProject(DbSession dbSession, AddRequest request) { + private Optional searchProject(DbSession dbSession, AddRequest request) { Optional project = request.getProject() == null ? empty() : Optional.of(componentFinder.getByKey(dbSession, request.getProject())); project.ifPresent(p -> checkRequest(Qualifiers.PROJECT.equals(p.qualifier()) && Scopes.PROJECT.equals(p.scope()), "Component '%s' must be a project", request.getProject())); - return project.orElse(null); + project.ifPresent(p -> userSession.checkComponentPermission(UserRole.USER, p)); + return project; } private void checkPermissions(AddRequest request) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java index 4f7437cca4a..3f024bd13ee 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -120,17 +121,28 @@ public class AddActionTest { } @Test - public void add_a_project_notification() { + public void add_notification_on_private_with_USER_permission() { ComponentDto project = db.components().insertPrivateProject(); + userSession.addProjectPermission(UserRole.USER, project); call(request.setProject(project.getDbKey())); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); } + @Test + public void add_notification_on_public_project() { + ComponentDto project = db.components().insertPublicProject(); + userSession.registerComponents(project); + call(request.setProject(project.getDbKey())); + + db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); + } + @Test public void add_a_global_notification_when_a_project_one_exists() { ComponentDto project = db.components().insertPrivateProject(); + userSession.addProjectPermission(UserRole.USER, project); call(request.setProject(project.getDbKey())); call(request.setProject(null)); @@ -140,10 +152,24 @@ public class AddActionTest { } @Test - public void add_a_project_notification_when_a_global_one_exists() { + public void add_a_notification_on_private_project_when_a_global_one_exists() { ComponentDto project = db.components().insertPrivateProject(); call(request); + userSession.addProjectPermission(UserRole.USER, project); + call(request.setProject(project.getDbKey())); + + db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); + db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), null); + } + + + @Test + public void add_a_notification_on_public_project_when_a_global_one_exists() { + ComponentDto project = db.components().insertPublicProject(); + userSession.registerComponents(project); + call(request); + call(request.setProject(project.getDbKey())); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); @@ -211,8 +237,19 @@ public class AddActionTest { } @Test - public void fail_when_unknown_project_dispatcher() { + public void fail_when_unknown_project_dispatcher_on_private_project() { ComponentDto project = db.components().insertPrivateProject(); + userSession.addProjectPermission(UserRole.USER, project); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]"); + + call(request.setType("Dispatcher42").setProject(project.getDbKey())); + } + + @Test + public void fail_when_unknown_project_dispatcher_on_public_project() { + ComponentDto project = db.components().insertPublicProject(); expectedException.expect(BadRequestException.class); expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]"); @@ -264,6 +301,18 @@ public class AddActionTest { call(request.setProject(branch.getDbKey())); } + @Test + public void fail_when_user_does_not_have_USER_permission_on_private_project() { + ComponentDto project = db.components().insertPrivateProject(); + userSession.logIn().setNonRoot().setNonSystemAdministrator(); + + expectedException.expect(ForbiddenException.class); + + call(request + .setProject(project.getDbKey()) + .setLogin(userSession.getLogin())); + } + private TestResponse call(AddRequest.Builder wsRequestBuilder) { AddRequest wsRequest = wsRequestBuilder.build(); TestRequest request = ws.newRequest(); -- 2.39.5