diff --git a/src/main/java/org/olat/basesecurity/BaseSecurity.java b/src/main/java/org/olat/basesecurity/BaseSecurity.java index fa3cc7f6a33397030397060fdc7191ee3bbea4f8..9345921f15feff147fbbb2aeefcd45d5f693b432 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurity.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurity.java @@ -68,6 +68,12 @@ public interface BaseSecurity { * @return The roles of the identity */ public Roles getRoles(Identity identity); + + /** + * Update the roles + * @param identity + */ + public void updateRoles(Identity identity, Roles roles); /** * @param identity diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java index 4973e2478b7fa81db03618967519ab4ac354bbde..91bd3c72ae3f84105e52044949ffdc4c20cc752e 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java @@ -341,7 +341,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { query.setString("permission", permission); query.setLong("resid", oresid); query.setString("resname", oresName); - query.setCacheable(true); + //query.setCacheable(true); List res = query.list(); Long cntL = (Long) res.get(0); return (cntL.longValue() > 0); // can be > 1 if identity is in more the one group having @@ -364,6 +364,61 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { return roles; } + @Override + public void updateRoles(Identity identity, Roles roles) { + SecurityGroup anonymousGroup = findSecurityGroupByName(Constants.GROUP_ANONYMOUS); + boolean hasBeenAnonymous = isIdentityInSecurityGroup(identity, anonymousGroup); + updateRolesInSecurityGroup(identity, anonymousGroup, hasBeenAnonymous, roles.isGuestOnly()); + + // system users - opposite of anonymous users + SecurityGroup usersGroup = findSecurityGroupByName(Constants.GROUP_OLATUSERS); + boolean hasBeenUser = isIdentityInSecurityGroup(identity, usersGroup); + updateRolesInSecurityGroup(identity, usersGroup, hasBeenUser, !roles.isGuestOnly()); + + SecurityGroup groupManagerGroup = findSecurityGroupByName(Constants.GROUP_GROUPMANAGERS); + boolean hasBeenGroupManager = isIdentityInSecurityGroup(identity, groupManagerGroup); + boolean groupManager = roles.isGroupManager() + && !roles.isGuestOnly() && !roles.isInvitee(); + updateRolesInSecurityGroup(identity, groupManagerGroup, hasBeenGroupManager, groupManager); + + // author + SecurityGroup authorGroup = findSecurityGroupByName(Constants.GROUP_AUTHORS); + boolean hasBeenAuthor = isIdentityInSecurityGroup(identity, authorGroup); + boolean isAuthor = (roles.isAuthor() || roles.isInstitutionalResourceManager()) + && !roles.isGuestOnly() && !roles.isInvitee(); + updateRolesInSecurityGroup(identity, authorGroup, hasBeenAuthor, isAuthor); + + // user manager, only allowed by admin + SecurityGroup userManagerGroup = findSecurityGroupByName(Constants.GROUP_USERMANAGERS); + boolean hasBeenUserManager = isIdentityInSecurityGroup(identity, userManagerGroup); + boolean userManager = roles.isUserManager() + && !roles.isGuestOnly() && !roles.isInvitee(); + updateRolesInSecurityGroup(identity, userManagerGroup, hasBeenUserManager, userManager); + + // institutional resource manager + SecurityGroup institutionalResourceManagerGroup = findSecurityGroupByName(Constants.GROUP_INST_ORES_MANAGER); + boolean hasBeenInstitutionalResourceManager = isIdentityInSecurityGroup(identity, institutionalResourceManagerGroup); + boolean institutionalResourceManager = roles.isInstitutionalResourceManager() + && !roles.isGuestOnly() && !roles.isInvitee(); + updateRolesInSecurityGroup(identity, institutionalResourceManagerGroup, hasBeenInstitutionalResourceManager, institutionalResourceManager); + + // system administrator + SecurityGroup adminGroup = findSecurityGroupByName(Constants.GROUP_ADMIN); + boolean hasBeenAdmin = isIdentityInSecurityGroup(identity, adminGroup); + boolean isOLATAdmin = roles.isOLATAdmin() && !roles.isGuestOnly() && !roles.isInvitee(); + updateRolesInSecurityGroup(identity, adminGroup, hasBeenAdmin, isOLATAdmin); + } + + private void updateRolesInSecurityGroup(Identity identity, SecurityGroup securityGroup, boolean hasBeenInGroup, boolean isNowInGroup) { + if (!hasBeenInGroup && isNowInGroup) { + // user not yet in security group, add him + addIdentityToSecurityGroup(identity, securityGroup); + } else if (hasBeenInGroup && !isNowInGroup) { + // user not anymore in security group, remove him + removeIdentityFromSecurityGroup(identity, securityGroup); + } + } + /** * scalar query : select sgi, poi, ori * @param identity diff --git a/src/main/java/org/olat/user/restapi/RolesVO.java b/src/main/java/org/olat/user/restapi/RolesVO.java new file mode 100644 index 0000000000000000000000000000000000000000..b99369dd2571ab25ec582ead959ea92eb8f10259 --- /dev/null +++ b/src/main/java/org/olat/user/restapi/RolesVO.java @@ -0,0 +1,89 @@ +package org.olat.user.restapi; + +import org.olat.core.id.Roles; + +public class RolesVO { + + private boolean olatAdmin = false; + private boolean userManager = false; + private boolean groupManager = false; + private boolean author = false; + private boolean guestOnly = false; + private boolean institutionalResourceManager = false; + private boolean invitee = false; + + public RolesVO() { + //for JAXB + } + + public RolesVO(Roles roles) { + this.olatAdmin = roles.isOLATAdmin(); + this.groupManager = roles.isGroupManager(); + this.userManager = roles.isUserManager(); + this.author = roles.isAuthor(); + this.guestOnly = roles.isGuestOnly(); + this.institutionalResourceManager = roles.isInstitutionalResourceManager(); + this.invitee = roles.isInvitee(); + } + + public Roles toRoles() { + return new Roles(olatAdmin, userManager, groupManager, author, guestOnly, institutionalResourceManager, invitee); + } + + public boolean isOlatAdmin() { + return olatAdmin; + } + + public void setOlatAdmin(boolean olatAdmin) { + this.olatAdmin = olatAdmin; + } + + public boolean isUserManager() { + return userManager; + } + + public void setUserManager(boolean userManager) { + this.userManager = userManager; + } + + public boolean isGroupManager() { + return groupManager; + } + + public void setGroupManager(boolean groupManager) { + this.groupManager = groupManager; + } + + public boolean isAuthor() { + return author; + } + + public void setAuthor(boolean author) { + this.author = author; + } + + public boolean isGuestOnly() { + return guestOnly; + } + + public void setGuestOnly(boolean guestOnly) { + this.guestOnly = guestOnly; + } + + public boolean isInstitutionalResourceManager() { + return institutionalResourceManager; + } + + public void setInstitutionalResourceManager(boolean institutionalResourceManager) { + this.institutionalResourceManager = institutionalResourceManager; + } + + public boolean isInvitee() { + return invitee; + } + + public void setInvitee(boolean invitee) { + this.invitee = invitee; + } + +} diff --git a/src/main/java/org/olat/user/restapi/UserWebService.java b/src/main/java/org/olat/user/restapi/UserWebService.java index e00e9901e64b9f6619a9ef1b8d2e7b4b79e77855..2416940118fb60469622b6021f2e7a59eee6ef09 100644 --- a/src/main/java/org/olat/user/restapi/UserWebService.java +++ b/src/main/java/org/olat/user/restapi/UserWebService.java @@ -69,6 +69,7 @@ import org.olat.core.gui.components.form.ValidationError; import org.olat.core.gui.translator.PackageTranslator; import org.olat.core.gui.translator.Translator; import org.olat.core.id.Identity; +import org.olat.core.id.Roles; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.logging.OLog; @@ -244,29 +245,60 @@ public class UserWebService { } /** - * Fallback method for browser - * @response.representation.qname {http://www.example.com}userVO - * @response.representation.mediaType application/xml, application/json - * @response.representation.doc The user to persist - * @response.representation.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO} + * Retrieves the roles of a user given its unique key identifier * @response.representation.200.mediaType application/xml, application/json - * @response.representation.200.doc The persisted user - * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVO} + * @response.representation.200.doc The user + * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_ROLESVO} * @response.representation.401.doc The roles of the authenticated user are not sufficient - * @response.representation.406.mediaType application/xml, application/json - * @response.representation.406.doc The list of errors - * @response.representation.406.example {@link org.olat.restapi.support.vo.Examples#SAMPLE_ERRORVOes} - * @param user The user to persist - * @param request The HTTP request - * @return the new persisted <code>User</code> + * @response.representation.404.doc The identity not found + * @param identityKey The user key identifier of the user being searched + * @param httpRequest The HTTP request + * @return an xml or json representation of a the roles being search. */ + @GET + @Path("{identityKey}/roles") + @Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) + public Response getRoles(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) { + try { + boolean isUserManager = isUserManager(request); + if(!isUserManager) { + return Response.serverError().status(Status.FORBIDDEN).build(); + } + Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false); + if(identity == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + + Roles roles = BaseSecurityManager.getInstance().getRoles(identity); + return Response.ok(new RolesVO(roles)).build(); + } catch (Throwable e) { + throw new WebApplicationException(e); + } + } + + @POST - @Path("new") - @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - public Response createPost(UserVO user, @Context HttpServletRequest request) { - return create(user, request); + @Path("{identityKey}/roles") + @Consumes({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_XML ,MediaType.APPLICATION_JSON}) + public Response updateRoles(@PathParam("identityKey") Long identityKey, RolesVO roles, @Context HttpServletRequest request) { + try { + boolean isUserManager = isUserManager(request); + if(!isUserManager) { + return Response.serverError().status(Status.FORBIDDEN).build(); + } + Identity identity = BaseSecurityManager.getInstance().loadIdentityByKey(identityKey, false); + if(identity == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + Roles modRoles = roles.toRoles(); + BaseSecurityManager.getInstance().updateRoles(identity, modRoles); + return Response.ok(new RolesVO(modRoles)).build(); + } catch (Throwable e) { + throw new WebApplicationException(e); + } } + /** * Retrieves an user given its unique key identifier diff --git a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java index 5a5555acf6d9614bdc7c0620788d43ca504844da..119b97ba0ac024277b053e6a181d3f4fd2dbc008 100644 --- a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java +++ b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -36,6 +35,7 @@ import org.junit.Assert; import org.junit.Test; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; +import org.olat.core.id.Roles; import org.olat.core.id.User; import org.olat.core.id.UserConstants; import org.olat.core.util.Encoder; @@ -258,6 +258,87 @@ public class BaseSecurityManagerTest extends OlatTestCase { Assert.assertTrue(identities.contains(id2)); } + /** + * Update roles + */ + @Test + public void testUpdateRoles_giveAllRights() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser( "roles-" + UUID.randomUUID().toString()); + Roles roles = securityManager.getRoles(id1); + Assert.assertNotNull(roles); + dbInstance.commitAndCloseSession(); + + //update roles + Roles modifiedRoles = new Roles(true, true, true, true, false, true, false); + securityManager.updateRoles(id1, modifiedRoles); + dbInstance.commitAndCloseSession(); + + //check roles + Roles reloadRoles = securityManager.getRoles(id1); + Assert.assertNotNull(reloadRoles); + Assert.assertTrue(reloadRoles.isAuthor()); + Assert.assertTrue(reloadRoles.isGroupManager()); + Assert.assertFalse(reloadRoles.isGuestOnly()); + Assert.assertTrue(reloadRoles.isInstitutionalResourceManager()); + Assert.assertFalse(reloadRoles.isInvitee()); + Assert.assertTrue(reloadRoles.isOLATAdmin()); + Assert.assertTrue(reloadRoles.isUserManager()); + } + + /** + * Update roles + */ + @Test + public void testUpdateRoles_someRights() { + Identity id1 = JunitTestHelper.createAndPersistIdentityAsUser( "roles-" + UUID.randomUUID().toString()); + Roles roles = securityManager.getRoles(id1); + Assert.assertNotNull(roles); + dbInstance.commitAndCloseSession(); + + //update roles + Roles modifiedRoles = new Roles(false, true, false, true, false, false, false); + securityManager.updateRoles(id1, modifiedRoles); + dbInstance.commitAndCloseSession(); + + //check roles + Roles reloadRoles = securityManager.getRoles(id1); + Assert.assertNotNull(reloadRoles); + Assert.assertTrue(reloadRoles.isAuthor()); + Assert.assertFalse(reloadRoles.isGroupManager()); + Assert.assertFalse(reloadRoles.isGuestOnly()); + Assert.assertFalse(reloadRoles.isInstitutionalResourceManager()); + Assert.assertFalse(reloadRoles.isInvitee()); + Assert.assertFalse(reloadRoles.isOLATAdmin()); + Assert.assertTrue(reloadRoles.isUserManager()); + } + + /** + * Update roles, check that invitee don't become rights + */ + @Test + public void testUpdateRoles_guest() { + Identity invitee = JunitTestHelper.createAndPersistIdentityAsUser("invitee-" + UUID.randomUUID().toString()); + Roles roles = securityManager.getRoles(invitee); + Assert.assertNotNull(roles); + dbInstance.commitAndCloseSession(); + + //update roles + Roles modifiedRoles = new Roles(true, true, true, true, true, true, false); + securityManager.updateRoles(invitee, modifiedRoles); + dbInstance.commitAndCloseSession(); + + //check roles + Roles reloadRoles = securityManager.getRoles(invitee); + Assert.assertNotNull(reloadRoles); + Assert.assertFalse(reloadRoles.isAuthor()); + Assert.assertFalse(reloadRoles.isGroupManager()); + Assert.assertTrue(reloadRoles.isGuestOnly()); + Assert.assertFalse(reloadRoles.isInstitutionalResourceManager()); + Assert.assertFalse(reloadRoles.isInvitee()); + Assert.assertFalse(reloadRoles.isOLATAdmin()); + Assert.assertFalse(reloadRoles.isUserManager()); + } + /** * Test method @see org.olat.basesecurity.BaseSecurityManager.getIdentitiesByPowerSearch() * with a list of identity keys as parameters.<br/> diff --git a/src/test/java/org/olat/restapi/UserMgmtTest.java b/src/test/java/org/olat/restapi/UserMgmtTest.java index bf33b73f43e79220446176105e5182353b300630..960afee3f1ea49e75b59218e2706c7284ca242ca 100644 --- a/src/test/java/org/olat/restapi/UserMgmtTest.java +++ b/src/test/java/org/olat/restapi/UserMgmtTest.java @@ -47,6 +47,8 @@ import javax.imageio.ImageIO; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriBuilder; +import junit.framework.Assert; + import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -68,9 +70,10 @@ import org.olat.collaboration.CollaborationToolsFactory; import org.olat.core.commons.modules.bc.FolderConfig; import org.olat.core.commons.modules.bc.vfs.OlatNamedContainerImpl; import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; -import org.olat.core.commons.persistence.DBFactory; +import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; +import org.olat.core.id.Roles; import org.olat.core.util.nodes.INode; import org.olat.core.util.resource.OresHelper; import org.olat.core.util.tree.TreeVisitor; @@ -104,6 +107,7 @@ import org.olat.restapi.support.vo.GroupVOes; import org.olat.test.JunitTestHelper; import org.olat.test.OlatJerseyTestCase; import org.olat.user.DisplayPortraitManager; +import org.olat.user.restapi.RolesVO; import org.olat.user.restapi.UserVO; import org.springframework.beans.factory.annotation.Autowired; @@ -129,8 +133,12 @@ public class UserMgmtTest extends OlatJerseyTestCase { private RestConnection conn; + @Autowired + DB dbInstance; @Autowired private BusinessGroupService businessGroupService; + @Autowired + private BaseSecurityManager securityManager; @Before @Override @@ -142,14 +150,14 @@ public class UserMgmtTest extends OlatJerseyTestCase { //create identities owner1 = JunitTestHelper.createAndPersistIdentityAsUser("user-rest-zero"); assertNotNull(owner1); - id1 = JunitTestHelper.createAndPersistIdentityAsUser("user-rest-one-" + UUID.randomUUID().toString().replace("-", "")); + id1 = JunitTestHelper.createAndPersistIdentityAsUser("user-rest-one-" + UUID.randomUUID().toString()); id2 = JunitTestHelper.createAndPersistIdentityAsUser("user-rest-two"); - DBFactory.getInstance().intermediateCommit(); + dbInstance.intermediateCommit(); id2.getUser().setProperty("telMobile", "39847592"); id2.getUser().setProperty("gender", "female"); id2.getUser().setProperty("birthDay", "20091212"); - DBFactory.getInstance().updateObject(id2.getUser()); - DBFactory.getInstance().intermediateCommit(); + dbInstance.updateObject(id2.getUser()); + dbInstance.intermediateCommit(); id3 = JunitTestHelper.createAndPersistIdentityAsUser("user-rest-three"); OlatRootFolderImpl id3HomeFolder = new OlatRootFolderImpl(FolderConfig.getUserHome(id3.getName()), null); @@ -168,8 +176,8 @@ public class UserMgmtTest extends OlatJerseyTestCase { // create course and persist as OLATResourceImpl OLATResourceable resourceable = OresHelper.createOLATResourceableInstance("junitcourse",System.currentTimeMillis()); OLATResource course = rm.createOLATResourceInstance(resourceable); - DBFactory.getInstance().saveObject(course); - DBFactory.getInstance().intermediateCommit(); + dbInstance.saveObject(course); + dbInstance.intermediateCommit(); //create learn group BaseSecurity secm = BaseSecurityManager.getInstance(); @@ -194,7 +202,7 @@ public class UserMgmtTest extends OlatJerseyTestCase { // members secm.addIdentityToSecurityGroup(id1, g3.getPartipiciantGroup()); secm.addIdentityToSecurityGroup(id2, g4.getPartipiciantGroup()); - DBFactory.getInstance().closeSession(); + dbInstance.closeSession(); //add some collaboration tools CollaborationTools g1CTSMngr = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(g1); @@ -205,7 +213,7 @@ public class UserMgmtTest extends OlatJerseyTestCase { m1.setBody("Body of Thread-1"); ForumManager.getInstance().addTopMessage(id1, g1Forum, m1); - DBFactory.getInstance().commitAndCloseSession(); + dbInstance.commitAndCloseSession(); //add some folder tool CollaborationTools g2CTSMngr = CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(g2); @@ -219,7 +227,7 @@ public class UserMgmtTest extends OlatJerseyTestCase { FileUtils.copyFileToDirectory(ioPortrait, g2Folder.getBasefile(), false); } - DBFactory.getInstance().commitAndCloseSession(); + dbInstance.commitAndCloseSession(); //prepare some courses RepositoryEntry entry = JunitTestHelper.deployDemoCourse(); @@ -262,7 +270,7 @@ public class UserMgmtTest extends OlatJerseyTestCase { }, demoCourse.getRunStructure().getRootNode(), false); visitor.visitAll(); - DBFactory.getInstance().commitAndCloseSession(); + dbInstance.commitAndCloseSession(); setuped = true; } @@ -272,7 +280,7 @@ public class UserMgmtTest extends OlatJerseyTestCase { if(conn != null) { conn.shutdown(); } - DBFactory.getInstance().closeSession(); + dbInstance.closeSession(); } catch (Exception e) { e.printStackTrace(); throw e; @@ -555,6 +563,62 @@ public class UserMgmtTest extends OlatJerseyTestCase { assertEquals(Identity.STATUS_DELETED, deletedIdent.getStatus()); } + @Test + public void testGetRoles() throws IOException, URISyntaxException { + //create an author + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("author-" + UUID.randomUUID().toString()); + dbInstance.commitAndCloseSession(); + + assertTrue(conn.login("administrator", "openolat")); + + //get roles of author + URI request = UriBuilder.fromUri(getContextURI()).path("/users/" + author.getKey() + "/roles").build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + HttpResponse response = conn.execute(method); + assertEquals(200, response.getStatusLine().getStatusCode()); + RolesVO roles = conn.parse(response, RolesVO.class); + Assert.assertNotNull(roles); + Assert.assertTrue(roles.isAuthor()); + Assert.assertFalse(roles.isGroupManager()); + Assert.assertFalse(roles.isGuestOnly()); + Assert.assertFalse(roles.isInstitutionalResourceManager()); + Assert.assertFalse(roles.isInvitee()); + Assert.assertFalse(roles.isOlatAdmin()); + Assert.assertFalse(roles.isUserManager()); + } + + @Test + public void testUpdateRoles() throws IOException, URISyntaxException { + //create an author + Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("author-" + UUID.randomUUID().toString()); + dbInstance.commitAndCloseSession(); + + assertTrue(conn.login("administrator", "openolat")); + + RolesVO roles = new RolesVO(); + roles.setAuthor(true); + roles.setUserManager(true); + + //get roles of author + URI request = UriBuilder.fromUri(getContextURI()).path("/users/" + author.getKey() + "/roles").build(); + HttpPost method = conn.createPost(request, MediaType.APPLICATION_JSON, true); + conn.addJsonEntity(method, roles); + HttpResponse response = conn.execute(method); + assertEquals(200, response.getStatusLine().getStatusCode()); + RolesVO modRoles = conn.parse(response, RolesVO.class); + Assert.assertNotNull(modRoles); + + //check the roles + Roles reloadRoles = securityManager.getRoles(author); + Assert.assertTrue(reloadRoles.isAuthor()); + Assert.assertFalse(reloadRoles.isGroupManager()); + Assert.assertFalse(reloadRoles.isGuestOnly()); + Assert.assertFalse(reloadRoles.isInstitutionalResourceManager()); + Assert.assertFalse(reloadRoles.isInvitee()); + Assert.assertFalse(reloadRoles.isOLATAdmin()); + Assert.assertTrue(reloadRoles.isUserManager()); + } + @Test public void testUserForums() throws IOException, URISyntaxException { assertTrue(conn.login(id1.getName(), "A6B7C8"));