diff --git a/src/main/java/org/olat/basesecurity/OrganisationService.java b/src/main/java/org/olat/basesecurity/OrganisationService.java index 0005eb2756bda341396bb5f3d32354d25e4b9b0b..6eda45de1d34f1917184637d86e91865ee22ce40 100644 --- a/src/main/java/org/olat/basesecurity/OrganisationService.java +++ b/src/main/java/org/olat/basesecurity/OrganisationService.java @@ -147,12 +147,25 @@ public interface OrganisationService { public List<OrganisationType> getOrganisationTypes(); /** + * The list of all organizations where the user has the specified roles, + * with inheritance in the organization structure dependent of the role. + * * @param member The user (mandatory) * @param role The roles (mandatory) * @return A list of organization where the user has the specified roles */ public List<Organisation> getOrganisations(IdentityRef member, OrganisationRoles... role); + /** + * The list of organizations where the user has the specified roles, + * without any inheritance in the organization structure. + * + * @param member The user (mandatory) + * @param role The roles (mandatory) + * @return A list of organization where the user has the specified roles + */ + public List<Organisation> getOrganisationsNotInherited(IdentityRef member, OrganisationRoles... role); + /** * Return the organization the specified user is allow to see. * An OpenOLAT admin. can see all organizations. diff --git a/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java b/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java index 5d6f56b2e945ecded2547d9ea503f1193261c3d4..45b9539a2ed267183198b782d74221867a32275c 100644 --- a/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java +++ b/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java @@ -314,7 +314,7 @@ public class OrganisationDAO { .getResultList(); } - public List<Organisation> getOrganisations(IdentityRef identity, List<String> roleList) { + public List<Organisation> getOrganisations(IdentityRef identity, List<String> roleList, boolean withInheritence) { QueryBuilder sb = new QueryBuilder(256); sb.append("select org from organisation org") .append(" inner join fetch org.group baseGroup") @@ -323,6 +323,9 @@ public class OrganisationDAO { .append(" left join fetch org.parent parentOrg") .append(" where membership.identity.key=:identityKey and membership.role in (:roles)") .append(" and org.status ").in(OrganisationStatus.notDelete()); + if(!withInheritence) { + sb.append(" and membership.inheritanceModeString ").in(GroupMembershipInheritance.root, GroupMembershipInheritance.none); + } List<Organisation> organisations = dbInstance.getCurrentEntityManager() .createQuery(sb.toString(), Organisation.class) .setParameter("identityKey", identity.getKey()) diff --git a/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java b/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java index 34eba1d17d42a6736427bc63958e865a8a4257b6..dafcd20fc8919b191c6a469041592966cb28aaa3 100644 --- a/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java +++ b/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java @@ -339,7 +339,16 @@ public class OrganisationServiceImpl implements OrganisationService, Initializin for(OrganisationRoles r:role) { roleList.add(r.name()); } - return organisationDao.getOrganisations(member, roleList); + return organisationDao.getOrganisations(member, roleList, true); + } + + @Override + public List<Organisation> getOrganisationsNotInherited(IdentityRef member, OrganisationRoles... role) { + List<String> roleList = new ArrayList<>(role.length); + for(OrganisationRoles r:role) { + roleList.add(r.name()); + } + return organisationDao.getOrganisations(member, roleList, false); } @Override diff --git a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java index ce68080c6c085a66cd220fd01ef3ae537e0f618e..c188eb4d452673450554f518f10e3095c693965c 100644 --- a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java +++ b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java @@ -39,11 +39,13 @@ import javax.ws.rs.core.Response.Status; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.GroupMembershipInheritance; +import org.olat.basesecurity.IdentityRef; import org.olat.basesecurity.OrganisationManagedFlag; import org.olat.basesecurity.OrganisationRoles; import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.OrganisationStatus; import org.olat.basesecurity.OrganisationType; +import org.olat.basesecurity.model.IdentityRefImpl; import org.olat.basesecurity.model.OrganisationRefImpl; import org.olat.basesecurity.model.OrganisationTypeRefImpl; import org.olat.core.commons.persistence.DB; @@ -172,6 +174,43 @@ public class OrganisationsWebService { return Response.ok(OrganisationVO.valueOf(savedOrganisation)).build(); } + /** + * Get the organizations where the specified user has the role. + * + * @response.representation.200.qname {http://www.example.com}organisationVO + * @response.representation.200.mediaType application/xml, application/json + * @response.representation.200.doc The list of organizations + * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_ORGANISATIONVO} + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @param role The role in organizations + * @param identityKey The user + * @param withInheritance With or without inheritance in the organization structure (default with) + * @param httpRequest The HTTP request + * @return The organization + */ + @GET + @Path("membership/{role}/{identityKey}") + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response getMemberships(@PathParam("role") String role, @PathParam("identityKey") Long identityKey, + @QueryParam("withInheritance") Boolean withInheritance, @Context HttpServletRequest httpRequest) { + if(!isAdministrator(httpRequest)) { + return Response.serverError().status(Status.UNAUTHORIZED).build(); + } + if(!OrganisationRoles.isValue(role)) { + return Response.serverError().status(Status.NOT_ACCEPTABLE).build(); + } + + IdentityRef member = new IdentityRefImpl(identityKey); + List<Organisation> organisations; + if(withInheritance == null || withInheritance.booleanValue()) { + organisations = organisationService.getOrganisations(member, OrganisationRoles.valueOf(role)); + } else { + organisations = organisationService.getOrganisationsNotInherited(member, OrganisationRoles.valueOf(role)); + } + OrganisationVO[] organisationVOes = toArrayOfVOes(organisations); + return Response.ok(organisationVOes).build(); + } + /** * Get a specific organization. * diff --git a/src/test/java/org/olat/basesecurity/manager/OrganisationDAOTest.java b/src/test/java/org/olat/basesecurity/manager/OrganisationDAOTest.java index b48b91a23c7a260ca3b0b33fa910dc579b8ea4c9..fa276d5982f5d1fc71a52326a066f0f25b1065b0 100644 --- a/src/test/java/org/olat/basesecurity/manager/OrganisationDAOTest.java +++ b/src/test/java/org/olat/basesecurity/manager/OrganisationDAOTest.java @@ -19,6 +19,8 @@ */ package org.olat.basesecurity.manager; +import static org.assertj.core.api.Assertions.assertThat; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -240,13 +242,13 @@ public class OrganisationDAOTest extends OlatTestCase { managerRoles.add(OrganisationRoles.usermanager.name()); managerRoles.add(OrganisationRoles.groupmanager.name()); managerRoles.add(OrganisationRoles.poolmanager.name()); - List<Organisation> managedOrganisations = organisationDao.getOrganisations(member, managerRoles); + List<Organisation> managedOrganisations = organisationDao.getOrganisations(member, managerRoles, true); Assert.assertEquals(2, managedOrganisations.size()); Assert.assertTrue(managedOrganisations.contains(organisation1)); Assert.assertTrue(managedOrganisations.contains(organisation3)); List<String> userRole = Collections.singletonList(OrganisationRoles.user.name()); - List<Organisation> organisations = organisationDao.getOrganisations(member, userRole); + List<Organisation> organisations = organisationDao.getOrganisations(member, userRole, true); Assert.assertEquals(4, organisations.size()); Assert.assertTrue(organisations.contains(organisation1)); Assert.assertTrue(organisations.contains(organisation2)); @@ -254,6 +256,32 @@ public class OrganisationDAOTest extends OlatTestCase { Assert.assertTrue(organisations.contains(defOrganisation)); } + @Test + public void getOrganisations_identity_notInherited() { + Identity member1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Member-16"); + Identity member2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Member-17"); + String identifier = UUID.randomUUID().toString(); + Organisation organisation1 = organisationDao.createAndPersistOrganisation("Org 10", identifier, null, null, null); + Organisation organisation1_1 = organisationDao.createAndPersistOrganisation("Org 11", identifier, null, organisation1, null); + Organisation organisation2 = organisationDao.createAndPersistOrganisation("Org 12", identifier, null, null, null); + dbInstance.commit(); + organisationService.addMember(organisation1, member1, OrganisationRoles.usermanager); + organisationService.addMember(organisation2, member1, OrganisationRoles.usermanager); + organisationService.addMember(organisation2, member2, OrganisationRoles.usermanager); + dbInstance.commitAndCloseSession(); + + List<String> managerRoles = new ArrayList<>(); + managerRoles.add(OrganisationRoles.usermanager.name()); + List<Organisation> organisationsFor1 = organisationDao.getOrganisations(member1, managerRoles, false); + assertThat(organisationsFor1) + .containsExactlyInAnyOrder(organisation1, organisation2) + .doesNotContain(organisation1_1); + + List<Organisation> organisationsFor2 = organisationDao.getOrganisations(member2, managerRoles, false); + assertThat(organisationsFor2) + .containsExactly(organisation2); + } + @Test public void getOrganisations_references() { String identifier = UUID.randomUUID().toString(); diff --git a/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java b/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java index 6703b659c3c4c31082b0bcc7faf9ba87dba435f1..1ae42828dd7145c6cfe72a0b4b5f94dafac4cbfd 100644 --- a/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java +++ b/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java @@ -20,6 +20,7 @@ package org.olat.restapi; import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.io.InputStream; @@ -460,7 +461,7 @@ public class OrganisationsWebServiceTest extends OlatJerseyTestCase { @Test public void getRepositoryEntries() throws IOException, URISyntaxException { - // prepare an organisation with a course + // prepare an organization with a course Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-13"); Organisation organisation = organisationService.createOrganisation("REST Organisation 8", "REST-p-8-organisation", "", null, null); organisationService.addMember(organisation, member, OrganisationRoles.administrator); @@ -483,7 +484,120 @@ public class OrganisationsWebServiceTest extends OlatJerseyTestCase { Assert.assertEquals(1, entries.size()); Assert.assertEquals(course.getKey(), entries.get(0).getKey()); } + + @Test + public void getMemberships() + throws IOException, URISyntaxException { + // prepare an organization with a course + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-14"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 9", "REST-p-9-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.author); + dbInstance.commit(); + + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path("membership") + .path("user").path(member.getKey().toString()).build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<OrganisationVO> organisations = parseOrganisationArray(response.getEntity()); + Assert.assertNotNull(organisations); + Assert.assertEquals(1, organisations.size()); + Assert.assertEquals(organisationService.getDefaultOrganisation().getKey(), organisations.get(0).getKey()); + } + + /** + * Default is with inheritance but be sure. + * + * @throws IOException + * @throws URISyntaxException + */ + @Test + public void getMemberships_usermanager() + throws IOException, URISyntaxException { + // prepare an organization with a course + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-16"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 14", "REST-p-14-organisation", "", null, null); + Organisation subOrganisation = organisationService.createOrganisation("REST Organisation 14b", "REST-p-14-b-organisation", "", organisation, null); + Organisation otherOrganisation = organisationService.createOrganisation("REST Organisation 15", "REST-p-16-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.rolesmanager); + organisationService.addMember(otherOrganisation, member, OrganisationRoles.rolesmanager); + dbInstance.commit(); + + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path("membership") + .path("rolesmanager").path(member.getKey().toString()).build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<OrganisationVO> organisations = parseOrganisationArray(response.getEntity()); + assertThat(organisations) + .extracting(OrganisationVO::getKey) + .containsExactlyInAnyOrder(organisation.getKey(), otherOrganisation.getKey(), subOrganisation.getKey()); + } + + @Test + public void getMemberships_usermanager_withInheritance() + throws IOException, URISyntaxException { + // prepare an organization with a course + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-17"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 16", "REST-p-16-organisation", "", null, null); + Organisation subOrganisation = organisationService.createOrganisation("REST Organisation 16b", "REST-p-16-b-organisation", "", organisation, null); + Organisation otherOrganisation = organisationService.createOrganisation("REST Organisation 17", "REST-p-17-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.usermanager); + organisationService.addMember(otherOrganisation, member, OrganisationRoles.usermanager); + dbInstance.commit(); + + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path("membership") + .path("usermanager").path(member.getKey().toString()).build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<OrganisationVO> organisations = parseOrganisationArray(response.getEntity()); + assertThat(organisations) + .extracting(OrganisationVO::getKey) + .containsExactlyInAnyOrder(organisation.getKey(), otherOrganisation.getKey(), subOrganisation.getKey()); + } + + @Test + public void getMemberships_usermanager_notInherited() + throws IOException, URISyntaxException { + // prepare an organization with a course + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-15"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 10", "REST-p-10-organisation", "", null, null); + Organisation subOrganisation = organisationService.createOrganisation("REST Organisation 11", "REST-p-11-organisation", "", organisation, null); + Organisation otherOrganisation = organisationService.createOrganisation("REST Organisation 12", "REST-p-12-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.usermanager); + organisationService.addMember(otherOrganisation, member, OrganisationRoles.usermanager); + dbInstance.commit(); + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path("membership") + .path("usermanager").path(member.getKey().toString()) + .queryParam("withInheritance", "false").build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<OrganisationVO> organisations = parseOrganisationArray(response.getEntity()); + assertThat(organisations) + .extracting(OrganisationVO::getKey) + .containsExactlyInAnyOrder(organisation.getKey(), otherOrganisation.getKey()) + .doesNotContain(subOrganisation.getKey()); + } + protected List<UserVO> parseUserArray(HttpEntity entity) { try(InputStream in=entity.getContent()) { ObjectMapper mapper = new ObjectMapper(jsonFactory);