From d8402b1a991fef1979d2ccaa610a9c3b9037ac4b Mon Sep 17 00:00:00 2001
From: anhefti <andreas.hefti@let.ethz.ch>
Date: Wed, 14 Aug 2019 16:43:23 +0200
Subject: [PATCH] SEBSERV-87 fix

---
 .../authorization/AuthorizationService.java   |  6 +--
 .../weblayer/api/EntityController.java        |  2 +-
 .../api/ExamMonitoringController.java         | 37 ++++++++++++++++++-
 .../AuthorizationServiceTest.java             |  6 +--
 4 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java
index 257b2744..a2834220 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java
@@ -137,11 +137,11 @@ public interface AuthorizationService {
                 currentUser.getUserRoles());
     }
 
-    /** Check read-only grant for a given Entity instance and current user.
+    /** Check read grant for a given Entity instance and current user.
      *
      * @param grantEntity Entity instance
-     * @return true if the current user has read-only grant on given Entity instance or false on deny */
-    default boolean hasReadonlyGrant(final GrantEntity grantEntity) {
+     * @return true if the current user has read grant on given Entity instance or false on deny */
+    default boolean hasReadGrant(final GrantEntity grantEntity) {
         return hasGrant(PrivilegeType.READ, grantEntity);
     }
 
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java
index 107605ab..33b4feec 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java
@@ -381,7 +381,7 @@ public abstract class EntityController<T extends Entity, M extends Entity> {
     protected boolean hasReadAccess(final T entity) {
         final GrantEntity grantEntity = toGrantEntity(entity);
         if (grantEntity != null) {
-            return this.authorization.hasReadonlyGrant(grantEntity);
+            return this.authorization.hasReadGrant(grantEntity);
         }
 
         return true;
diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java
index e701b8bb..152e69cb 100644
--- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java
+++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/ExamMonitoringController.java
@@ -30,9 +30,9 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
 import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
 import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
-import ch.ethz.seb.sebserver.gbl.util.Utils;
 import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
 import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
+import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
 import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
 import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
 import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
@@ -113,7 +113,9 @@ public class ExamMonitoringController {
         }
 
         final List<Exam> exams = new ArrayList<>(this.examSessionService
-                .getFilteredRunningExams(filterMap, Utils.truePredicate())
+                .getFilteredRunningExams(
+                        filterMap,
+                        exam -> this.hasRunningExamPrivilege(exam, institutionId))
                 .getOrThrow());
 
         return ExamAdministrationController.buildSortedExamPage(
@@ -135,11 +137,20 @@ public class ExamMonitoringController {
                     defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
             @PathVariable(name = API.EXAM_API_PARAM_EXAM_ID, required = true) final Long examId) {
 
+        // check overall privilege
         this.authorization.checkRole(
                 institutionId,
                 EntityType.EXAM,
                 UserRole.EXAM_SUPPORTER);
 
+        // check running exam privilege for specified exam
+        if (!hasRunningExamPrivilege(examId, institutionId)) {
+            throw new PermissionDeniedException(
+                    EntityType.EXAM,
+                    PrivilegeType.READ,
+                    this.authorization.getUserService().getCurrentUser().getUserInfo());
+        }
+
         return this.examSessionService
                 .getConnectionData(examId)
                 .getOrThrow();
@@ -158,14 +169,36 @@ public class ExamMonitoringController {
             @PathVariable(name = API.EXAM_API_PARAM_EXAM_ID, required = true) final Long examId,
             @PathVariable(name = API.EXAM_API_SEB_CONNECTION_TOKEN, required = true) final String connectionToken) {
 
+        // check overall privilege
         this.authorization.checkRole(
                 institutionId,
                 EntityType.EXAM,
                 UserRole.EXAM_SUPPORTER);
 
+        // check running exam privilege for specified exam
+        if (!hasRunningExamPrivilege(examId, institutionId)) {
+            throw new PermissionDeniedException(
+                    EntityType.EXAM,
+                    PrivilegeType.READ,
+                    this.authorization.getUserService().getCurrentUser().getUserInfo());
+        }
+
         return this.examSessionService
                 .getConnectionData(connectionToken)
                 .getOrThrow();
     }
 
+    private boolean hasRunningExamPrivilege(final Long examId, final Long institution) {
+        return hasRunningExamPrivilege(
+                this.examSessionService.getRunningExam(examId).getOr(null),
+                institution);
+    }
+
+    private boolean hasRunningExamPrivilege(final Exam exam, final Long institution) {
+        if (exam == null) {
+            return false;
+        }
+        return exam.institutionId.equals(institution) && this.authorization.hasReadGrant(exam);
+    }
+
 }
diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java
index 2b718ff3..ee64ff7f 100644
--- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java
+++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java
@@ -42,7 +42,7 @@ public class AuthorizationServiceTest {
 
         final GrantEntity institution = entityOf(EntityType.INSTITUTION, 2L, "");
 
-        assertTrue(service.hasReadonlyGrant(institution));
+        assertTrue(service.hasReadGrant(institution));
         assertTrue(service.hasModifyGrant(institution));
         assertTrue(service.hasWriteGrant(institution));
     }
@@ -57,13 +57,13 @@ public class AuthorizationServiceTest {
 
         final GrantEntity ownInstitution = entityOf(EntityType.INSTITUTION, 1L, "");
 
-        assertTrue(service.hasReadonlyGrant(ownInstitution));
+        assertTrue(service.hasReadGrant(ownInstitution));
         assertTrue(service.hasModifyGrant(ownInstitution));
         assertFalse(service.hasWriteGrant(ownInstitution));
 
         final GrantEntity otherInstitution = entityOf(EntityType.INSTITUTION, 2L, "");
 
-        assertFalse(service.hasReadonlyGrant(otherInstitution));
+        assertFalse(service.hasReadGrant(otherInstitution));
         assertFalse(service.hasModifyGrant(otherInstitution));
         assertFalse(service.hasWriteGrant(otherInstitution));
     }