From 4b7d41f4ace08f63391ef9fb24fba55adf22926e Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Mon, 24 Feb 2020 11:35:26 +0100
Subject: [PATCH] no-jira: allow a user to know its roles per REST API

---
 .../restapi/security/RestSecurityHelper.java  |  5 +++
 .../org/olat/user/restapi/UserWebService.java | 14 +++----
 .../java/org/olat/restapi/UserMgmtTest.java   | 42 +++++++++++++++----
 3 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/olat/restapi/security/RestSecurityHelper.java b/src/main/java/org/olat/restapi/security/RestSecurityHelper.java
index 50342898ed7..7057d919cad 100644
--- a/src/main/java/org/olat/restapi/security/RestSecurityHelper.java
+++ b/src/main/java/org/olat/restapi/security/RestSecurityHelper.java
@@ -55,6 +55,11 @@ public class RestSecurityHelper {
 		return (UserRequest)request.getAttribute(SEC_USER_REQUEST);
 	}
 	
+	public static boolean itself(Long identityKey, HttpServletRequest request) {
+		Identity identity = getIdentity(request);
+		return identityKey != null && identity != null && identityKey.equals(identity.getKey());
+	}
+	
 	public static Identity getIdentity(HttpServletRequest request) {
 		UserRequest ureq = (UserRequest)request.getAttribute(SEC_USER_REQUEST);
 		if(ureq == null) return null;
diff --git a/src/main/java/org/olat/user/restapi/UserWebService.java b/src/main/java/org/olat/user/restapi/UserWebService.java
index e70174d9674..63fc2c68ab0 100644
--- a/src/main/java/org/olat/user/restapi/UserWebService.java
+++ b/src/main/java/org/olat/user/restapi/UserWebService.java
@@ -24,6 +24,7 @@ import static org.olat.restapi.security.RestSecurityHelper.getIdentity;
 import static org.olat.restapi.security.RestSecurityHelper.getLocale;
 import static org.olat.restapi.security.RestSecurityHelper.getRoles;
 import static org.olat.restapi.security.RestSecurityHelper.getUserRequest;
+import static org.olat.restapi.security.RestSecurityHelper.itself;
 import static org.olat.user.restapi.UserVOFactory.formatDbUserProperty;
 import static org.olat.user.restapi.UserVOFactory.get;
 import static org.olat.user.restapi.UserVOFactory.getManaged;
@@ -405,15 +406,14 @@ public class UserWebService {
 	@GET
 	@Path("{identityKey}/roles")
 	@Operation(summary = "Retrieve the roles", description = "Retrieves the roles of a user given its unique key identifier")
-	@ApiResponses({
-			@ApiResponse(responseCode = "200", description = "The user", content = {
-					@Content(mediaType = "application/json", schema = @Schema(implementation = RolesVO.class)),
-					@Content(mediaType = "application/xml", schema = @Schema(implementation = RolesVO.class)) }),
-			@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient"),
-			@ApiResponse(responseCode = "404", description = "The identity not found")})	
+	@ApiResponse(responseCode = "200", description = "The user", content = {
+			@Content(mediaType = "application/json", schema = @Schema(implementation = RolesVO.class)),
+			@Content(mediaType = "application/xml", schema = @Schema(implementation = RolesVO.class)) })
+	@ApiResponse(responseCode = "401", description = "The roles of the authenticated user are not sufficient")
+	@ApiResponse(responseCode = "404", description = "The identity not found")
 	@Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON})
 	public Response getIdentityRoles(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
-		if(!isUserManagerOf(identityKey, request)) {
+		if(!isUserManagerOf(identityKey, request) && !itself(identityKey, request)) {
 			return Response.serverError().status(Status.FORBIDDEN).build();
 		}
 		Identity identity = securityManager.loadIdentityByKey(identityKey, false);
diff --git a/src/test/java/org/olat/restapi/UserMgmtTest.java b/src/test/java/org/olat/restapi/UserMgmtTest.java
index 20c3ffa9609..9e33aea8deb 100644
--- a/src/test/java/org/olat/restapi/UserMgmtTest.java
+++ b/src/test/java/org/olat/restapi/UserMgmtTest.java
@@ -514,9 +514,7 @@ public class UserMgmtTest extends OlatRestTestCase {
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
 		String bodyJson = EntityUtils.toString(response.getEntity());
-		System.out.println("User");
-		System.out.println(bodyJson);
-		System.out.println("User");
+		log.info("User JSON: {}", bodyJson);
 		conn.shutdown();
 	}
 		
@@ -534,9 +532,7 @@ public class UserMgmtTest extends OlatRestTestCase {
 		HttpResponse response = conn.execute(method);
 		assertEquals(200, response.getStatusLine().getStatusCode());
 		String bodyXml = EntityUtils.toString(response.getEntity());
-		System.out.println("User");
-		System.out.println(bodyXml);
-		System.out.println("User");
+		log.info("User XML: {}", bodyXml);
 		conn.shutdown();
 	}
 	
@@ -1054,6 +1050,38 @@ public class UserMgmtTest extends OlatRestTestCase {
 		conn.shutdown();
 	}
 	
+	@Test
+	public void getRoles_itself() throws IOException, URISyntaxException {
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login(id1.getName(), JunitTestHelper.PWD));
+
+		URI rolesUri = UriBuilder.fromUri(getContextURI())
+			.path("users").path(id1.getKey().toString()).path("roles").build();
+		
+		HttpGet method = conn.createGet(rolesUri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+		RolesVO vo = conn.parse(response, RolesVO.class);
+		Assert.assertNotNull(vo);
+		Assert.assertFalse(vo.isInvitee());
+		Assert.assertFalse(vo.isGuestOnly());
+		conn.shutdown();
+	}
+	
+	@Test
+	public void getRoles_notItself() throws IOException, URISyntaxException {
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login(id1.getName(), JunitTestHelper.PWD));
+
+		URI rolesUri = UriBuilder.fromUri(getContextURI())
+			.path("users").path(id2.getKey().toString()).path("roles").build();
+		
+		HttpGet method = conn.createGet(rolesUri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		Assert.assertEquals(403, response.getStatusLine().getStatusCode());
+		conn.shutdown();
+	}
+	
 	@Test
 	public void testUpdateRoles() throws IOException, URISyntaxException {
 		//create an author
@@ -1797,7 +1825,7 @@ public class UserMgmtTest extends OlatRestTestCase {
 		assertEquals(200, headSmallResponse.getStatusLine().getStatusCode());
 		EntityUtils.consume(headSmallResponse.getEntity());
 	}
-	
+
 	protected List<UserVO> parseUserArray(HttpEntity entity) {
 		try(InputStream in=entity.getContent()) {
 			ObjectMapper mapper = new ObjectMapper(jsonFactory); 
-- 
GitLab