From 5149f150bdaddf0c10e1165da0d04fb4aecd239b Mon Sep 17 00:00:00 2001
From: Paul-Christian Volkmer <paul-christian.volkmer@mni.thm.de>
Date: Wed, 21 May 2014 11:25:13 +0200
Subject: [PATCH] Reworked permission evaluator for use with all types of
 authentication

---
 .../ApplicationPermissionEvaluator.java       | 36 +++++++++++--------
 .../thm/arsnova/services/QuestionService.java |  9 +----
 .../thm/arsnova/services/SessionService.java  |  3 +-
 .../arsnova/services/QuestionServiceTest.java | 24 ++++++++++---
 .../arsnova/services/SessionServiceTest.java  |  4 +--
 5 files changed, 46 insertions(+), 30 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/security/ApplicationPermissionEvaluator.java b/src/main/java/de/thm/arsnova/security/ApplicationPermissionEvaluator.java
index 052b3cc5a..10cd0885d 100644
--- a/src/main/java/de/thm/arsnova/security/ApplicationPermissionEvaluator.java
+++ b/src/main/java/de/thm/arsnova/security/ApplicationPermissionEvaluator.java
@@ -4,46 +4,54 @@ import java.io.Serializable;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.PermissionEvaluator;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
 import org.springframework.security.core.Authentication;
-import org.springframework.security.core.userdetails.UserDetails;
 
 import de.thm.arsnova.dao.IDatabaseDao;
+import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 
 public class ApplicationPermissionEvaluator implements PermissionEvaluator {
 
 	@Autowired
-	IDatabaseDao dao;
+	private IDatabaseDao dao;
 
 	@Override
 	public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
-		UserDetails user = getUserDetails(authentication);
-		return false;
+		String username = getUsername(authentication);
+
+		if (
+				targetDomainObject instanceof Session
+				&& ! checkSessionPermission(username, ((Session)targetDomainObject).getKeyword(), permission)
+				) {
+			throw new ForbiddenException();
+		}
+		return true;
 	}
 
 	@Override
 	public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
-		UserDetails user = getUserDetails(authentication);
+		String username = getUsername(authentication);
 
-		if ("session".equals(targetType)) {
-			return checkSessionPermission(user, targetId, permission);
+		if ("session".equals(targetType) && ! checkSessionPermission(username, targetId, permission)) {
+			throw new ForbiddenException();
 		}
-		return false;
+		return true;
 	}
 
-	private boolean checkSessionPermission(UserDetails user, Serializable targetId, Object permission) {
+	private boolean checkSessionPermission(String username, Serializable targetId, Object permission) {
 		if (permission instanceof String && permission.equals("owner")) {
-			return dao.getSession(targetId.toString()).getCreator().equals(user.getUsername());
+			return dao.getSession(targetId.toString()).getCreator().equals(username);
 		}
 		return false;
 	}
 
-	private UserDetails getUserDetails(Authentication authentication)
-			throws UnauthorizedException {
-		if (authentication.getPrincipal() == null || authentication.getPrincipal() instanceof String) {
+	private String getUsername(Authentication authentication) {
+		if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
 			throw new UnauthorizedException();
 		}
 
-		return (UserDetails)authentication.getPrincipal();
+		return authentication.getName();
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java
index b47fc1d47..b68df9615 100644
--- a/src/main/java/de/thm/arsnova/services/QuestionService.java
+++ b/src/main/java/de/thm/arsnova/services/QuestionService.java
@@ -40,7 +40,6 @@ import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
 import de.thm.arsnova.entities.User;
 import de.thm.arsnova.exceptions.BadRequestException;
-import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
 import de.thm.arsnova.exceptions.UnauthorizedException;
 import de.thm.arsnova.socket.ARSnovaSocketIOServer;
@@ -80,17 +79,11 @@ public class QuestionService implements IQuestionService {
 	}
 
 	@Override
-	@PreAuthorize("isAuthenticated()")
+	@PreAuthorize("isAuthenticated() and hasPermission(#question.getSessionKeyword(), 'session', 'owner')")
 	public Question saveQuestion(Question question) {
 		Session session = this.databaseDao.getSessionFromKeyword(question.getSessionKeyword());
 		question.setSessionId(session.get_id());
 
-		User user = userService.getCurrentUser();
-
-		if (! session.isCreator(user)) {
-			throw new ForbiddenException();
-		}
-
 		if ("freetext".equals(question.getQuestionType())) {
 			question.setPiRound(0);
 		} else if (question.getPiRound() < 1 || question.getPiRound() > 2) {
diff --git a/src/main/java/de/thm/arsnova/services/SessionService.java b/src/main/java/de/thm/arsnova/services/SessionService.java
index 79f98a6eb..816ea4607 100644
--- a/src/main/java/de/thm/arsnova/services/SessionService.java
+++ b/src/main/java/de/thm/arsnova/services/SessionService.java
@@ -234,7 +234,8 @@ public class SessionService implements ISessionService {
 	}
 
 	@Override
-	@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
+	@PreAuthorize("isAuthenticated() and hasPermission(#session, 'owner')")
+	//@PreAuthorize("isAuthenticated() and hasPermission(#sessionkey, 'session', 'owner')")
 	public Session updateSession(String sessionkey, Session session) {
 		return databaseDao.updateSession(session);
 	}
diff --git a/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java b/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
index 64e251fc3..4fb11fe63 100644
--- a/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/QuestionServiceTest.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,6 +39,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 import de.thm.arsnova.dao.StubDatabaseDao;
 import de.thm.arsnova.entities.InterposedQuestion;
+import de.thm.arsnova.entities.Question;
+import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
 
 @RunWith(SpringJUnit4ClassRunner.class)
@@ -65,17 +68,19 @@ public class QuestionServiceTest {
 			SecurityContextHolder.getContext().setAuthentication(token);
 			userService.setUserAuthenticated(isAuthenticated, username);
 		} else {
-			SecurityContextHolder.setContext(
-					SecurityContextHolder.createEmptyContext()
-					);
 			userService.setUserAuthenticated(isAuthenticated);
 		}
 	}
 
+	@Before
+	public final void startup() {
+		SecurityContextHolder.clearContext();
+	}
+
 	@After
 	public final void cleanup() {
-		databaseDao.cleanupTestData();
-		setAuthenticated(false, "ptsr00");
+		//databaseDao.cleanupTestData();
+		//setAuthenticated(false, "ptsr00");
 	}
 
 	@Test(expected = AuthenticationCredentialsNotFoundException.class)
@@ -123,4 +128,13 @@ public class QuestionServiceTest {
 
 		assertFalse(theQ.isRead());
 	}
+
+	@Test(expected = ForbiddenException.class)
+	public void testShouldSaveQuestion() throws Exception{
+		setAuthenticated(true, "regular user");
+		Question question = new Question();
+		question.setSessionKeyword("12345678");
+		question.setQuestionVariant("freetext");
+		questionService.saveQuestion(question);
+	}
 }
diff --git a/src/test/java/de/thm/arsnova/services/SessionServiceTest.java b/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
index a294544b9..c8ee1deca 100644
--- a/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
+++ b/src/test/java/de/thm/arsnova/services/SessionServiceTest.java
@@ -48,8 +48,8 @@ import de.thm.arsnova.dao.IDatabaseDao;
 import de.thm.arsnova.dao.StubDatabaseDao;
 import de.thm.arsnova.entities.Question;
 import de.thm.arsnova.entities.Session;
+import de.thm.arsnova.exceptions.ForbiddenException;
 import de.thm.arsnova.exceptions.NotFoundException;
-import de.thm.arsnova.exceptions.UnauthorizedException;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(locations = {
@@ -135,7 +135,7 @@ public class SessionServiceTest {
 		assertNotNull(sessionService.joinSession("11111111"));
 	}
 
-	@Test(expected = UnauthorizedException.class)
+	@Test(expected = ForbiddenException.class)
 	public void testShouldUpdateSession() {
 		setAuthenticated(true, "ptsr00");
 
-- 
GitLab