diff --git a/src/main/java/org/olat/basesecurity/OrganisationRoles.java b/src/main/java/org/olat/basesecurity/OrganisationRoles.java index cd893cf75cdf5a8eb15e82b8f11a7e79b97f3db2..893faf08dce7cc05e68389cdd97c17659afa97f0 100644 --- a/src/main/java/org/olat/basesecurity/OrganisationRoles.java +++ b/src/main/java/org/olat/basesecurity/OrganisationRoles.java @@ -36,6 +36,7 @@ public enum OrganisationRoles { groupmanager, poolmanager, curriculummanager, + principal, author, coach, user, @@ -71,6 +72,7 @@ public enum OrganisationRoles { groupmanager, poolmanager, curriculummanager, + principal, author, user, }; diff --git a/src/main/java/org/olat/basesecurity/OrganisationService.java b/src/main/java/org/olat/basesecurity/OrganisationService.java index 8057ea50f5d963a8153c1ce66b3398483c0df3b7..b7544495c1eae77e77241b3b558937de1f964d71 100644 --- a/src/main/java/org/olat/basesecurity/OrganisationService.java +++ b/src/main/java/org/olat/basesecurity/OrganisationService.java @@ -182,6 +182,8 @@ public interface OrganisationService { public void setAsGuest(Identity identity); public List<OrganisationMember> getMembers(Organisation organisation); + + public List<Identity> getMembersIdentity(Organisation organisation, OrganisationRoles role); /** diff --git a/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java b/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java index afe789d65c0b25345fd52f054ccc4f0386c62f3a..0df54387447970281eb78612f7b3e1df6c09ad7c 100644 --- a/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java +++ b/src/main/java/org/olat/basesecurity/manager/OrganisationDAO.java @@ -196,6 +196,21 @@ public class OrganisationDAO { return members; } + public List<Identity> getMembersIdentity(OrganisationRef organisation, String role) { + StringBuilder sb = new StringBuilder(256); + sb.append("select ident from organisation org") + .append(" inner join org.group baseGroup") + .append(" inner join baseGroup.members membership") + .append(" inner join membership.identity ident") + .append(" inner join fetch ident.user identUser") + .append(" where org.key=:organisationKey and membership.role=:role"); + return dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), Identity.class) + .setParameter("organisationKey", organisation.getKey()) + .setParameter("role", role) + .getResultList(); + } + public List<Identity> getIdentities(String organisationIdentifier, String role) { StringBuilder sb = new StringBuilder(256); sb.append("select ident from organisation org") diff --git a/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java b/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java index e733d885178d34e802d1497ffad7c6997a1a590e..0f408ba86bce1fdfbee00974669f7a085fa4d635 100644 --- a/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java +++ b/src/main/java/org/olat/basesecurity/manager/OrganisationServiceImpl.java @@ -334,6 +334,11 @@ public class OrganisationServiceImpl implements OrganisationService, Initializin return organisationDao.getMembers(organisation); } + @Override + public List<Identity> getMembersIdentity(Organisation organisation, OrganisationRoles role) { + return organisationDao.getMembersIdentity(organisation, role.name()); + } + @Override public void setAsGuest(Identity identity) { OrganisationImpl defOrganisation = (OrganisationImpl)getDefaultOrganisation(); diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumRoles.java b/src/main/java/org/olat/modules/curriculum/CurriculumRoles.java index 1660c8e249d53124301e3dcf054a9806362ed893..f7ec99039f1669b7333fdcb93ecb7d786d569072 100644 --- a/src/main/java/org/olat/modules/curriculum/CurriculumRoles.java +++ b/src/main/java/org/olat/modules/curriculum/CurriculumRoles.java @@ -29,7 +29,7 @@ import org.olat.core.util.StringHelper; */ public enum CurriculumRoles { - supervisor, + curriculummanager, owner, //same as GroupRoles coach, //same as GroupRoles participant; //same as GroupRoles diff --git a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementsWebService.java b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementsWebService.java index 1b3b1406a923401ecfa2fe50b473664882fe72a0..3ff22a8cd14ae1833a7f94122a06c34a38c18919 100644 --- a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementsWebService.java +++ b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumElementsWebService.java @@ -475,6 +475,7 @@ public class CurriculumElementsWebService { */ @GET @Path("{curriculumElementKey}/participants") + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response getParticipants(@PathParam("curriculumElementKey") Long curriculumElementKey) { return getMembers(curriculumElementKey, CurriculumRoles.participant); } @@ -493,10 +494,49 @@ public class CurriculumElementsWebService { */ @GET @Path("{curriculumElementKey}/coaches") + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response getCoaches(@PathParam("curriculumElementKey") Long curriculumElementKey) { return getMembers(curriculumElementKey, CurriculumRoles.coach); } + /** + * Get all owners of the specified curriculum element. + * + * @response.representation.200.qname {http://www.example.com}userVO + * @response.representation.200.mediaType application/xml, application/json + * @response.representation.200.doc The array of coaches + * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes} + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element not found + * @param httpRequest The HTTP request + * @return It returns an array of <code>UserVO</code> + */ + @GET + @Path("{curriculumElementKey}/owners") + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response getOwners(@PathParam("curriculumElementKey") Long curriculumElementKey) { + return getMembers(curriculumElementKey, CurriculumRoles.owner); + } + + /** + * Get all curriculum managers of the specified curriculum element. + * + * @response.representation.200.qname {http://www.example.com}userVO + * @response.representation.200.mediaType application/xml, application/json + * @response.representation.200.doc The array of coaches + * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes} + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element not found + * @param httpRequest The HTTP request + * @return It returns an array of <code>UserVO</code> + */ + @GET + @Path("{curriculumElementKey}/curriculummanagers") + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response getCurriculumManagers(@PathParam("curriculumElementKey") Long curriculumElementKey) { + return getMembers(curriculumElementKey, CurriculumRoles.curriculummanager); + } + private Response getMembers(Long curriculumElementKey, CurriculumRoles role) { CurriculumElement curriculumElement = curriculumService.getCurriculumElement(new CurriculumElementRefImpl(curriculumElementKey)); if(curriculumElement == null) { @@ -545,6 +585,38 @@ public class CurriculumElementsWebService { return putMember(curriculumElementKey, identityKey, CurriculumRoles.coach); } + /** + * Make the specified user a course owner of the curriculum element. + * + * @response.representation.200.doc The membership was added + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @param curriculumElementKey The curriculum element primary key + * @param identityKey The member to make a course owner of + * @return Nothing + */ + @PUT + @Path("{curriculumElementKey}/owners/{identityKey}") + public Response putOwner(@PathParam("curriculumElementKey") Long curriculumElementKey, @PathParam("identityKey") Long identityKey) { + return putMember(curriculumElementKey, identityKey, CurriculumRoles.owner); + } + + /** + * Make the specified user a curricullum manager of the curriculum element. + * + * @response.representation.200.doc The membership was added + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @param curriculumElementKey The curriculum element primary key + * @param identityKey The member to make a curriculum manager of + * @return Nothing + */ + @PUT + @Path("{curriculumElementKey}/curriculummanagers/{identityKey}") + public Response putCurriculumManager(@PathParam("curriculumElementKey") Long curriculumElementKey, @PathParam("identityKey") Long identityKey) { + return putMember(curriculumElementKey, identityKey, CurriculumRoles.curriculummanager); + } + private Response putMember(Long curriculumElementKey, Long identityKey, CurriculumRoles role) { CurriculumElement curriculumElement = curriculumService.getCurriculumElement(new CurriculumElementRefImpl(curriculumElementKey)); if(curriculumElement == null) { @@ -579,6 +651,7 @@ public class CurriculumElementsWebService { */ @PUT @Path("{curriculumElementKey}/participants") + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response putParticipants(@PathParam("curriculumElementKey") Long curriculumElementKey, UserVO[] participants) { return putMembers(curriculumElementKey, participants, CurriculumRoles.participant); } @@ -600,10 +673,55 @@ public class CurriculumElementsWebService { */ @PUT @Path("{curriculumElementKey}/coaches") - public Response putCoach(@PathParam("curriculumElementKey") Long curriculumElementKey, UserVO[] coaches) { + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response putCoaches(@PathParam("curriculumElementKey") Long curriculumElementKey, UserVO[] coaches) { return putMembers(curriculumElementKey, coaches, CurriculumRoles.coach); } + /** + * Make the array of users course owner of the specified curriculum element. + * + * @response.representation.qname {http://www.example.com}userVO + * @response.representation.mediaType application/xml, application/json + * @response.representation.doc The curriculum element membership to persist + * @response.representation.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes} + * @response.representation.200.doc The memberships was persisted + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @response.representation.409.doc The role is not allowed + * @param curriculumElementKey The curriculum element primary key + * @param participants The future course owners + * @return Nothing + */ + @PUT + @Path("{curriculumElementKey}/owners") + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response putOwners(@PathParam("curriculumElementKey") Long curriculumElementKey, UserVO[] coaches) { + return putMembers(curriculumElementKey, coaches, CurriculumRoles.owner); + } + + /** + * Make the array of users curriculum managers of the specified curriculum element. + * + * @response.representation.qname {http://www.example.com}userVO + * @response.representation.mediaType application/xml, application/json + * @response.representation.doc The curriculum element membership to persist + * @response.representation.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes} + * @response.representation.200.doc The memberships was persisted + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @response.representation.409.doc The role is not allowed + * @param curriculumElementKey The curriculum element primary key + * @param participants The future curriculum manages + * @return Nothing + */ + @PUT + @Path("{curriculumElementKey}/curriculummanagers") + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response putCurriculumManagers(@PathParam("curriculumElementKey") Long curriculumElementKey, UserVO[] coaches) { + return putMembers(curriculumElementKey, coaches, CurriculumRoles.curriculummanager); + } + private Response putMembers(Long curriculumElementKey, UserVO[] members, CurriculumRoles role) { CurriculumElement curriculumElement = curriculumService.getCurriculumElement(new CurriculumElementRefImpl(curriculumElementKey)); if(curriculumElement == null) { @@ -656,6 +774,40 @@ public class CurriculumElementsWebService { return deleteMember(curriculumElementKey, identityKey, CurriculumRoles.coach); } + /** + * Remove the owner membership of the identity from the specified curriculum element. + * + * @response.representation.200.doc The membership was removed + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @param curriculumElementKey The curriculum element primary key + * @param identityKey The member to remove + * @return Nothing + */ + @DELETE + @Path("{curriculumElementKey}/owners/{identityKey}") + public Response deleteOwner(@PathParam("curriculumElementKey") Long curriculumElementKey, + @PathParam("identityKey") Long identityKey) { + return deleteMember(curriculumElementKey, identityKey, CurriculumRoles.owner); + } + + /** + * Remove the curriculum manager membership of the identity from the specified curriculum element. + * + * @response.representation.200.doc The membership was removed + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @param curriculumElementKey The curriculum element primary key + * @param identityKey The member to remove + * @return Nothing + */ + @DELETE + @Path("{curriculumElementKey}/curriculummanagers/{identityKey}") + public Response deleteCurriculumManager(@PathParam("curriculumElementKey") Long curriculumElementKey, + @PathParam("identityKey") Long identityKey) { + return deleteMember(curriculumElementKey, identityKey, CurriculumRoles.curriculummanager); + } + private Response deleteMember(Long curriculumElementKey, Long identityKey, CurriculumRoles role) { CurriculumElement curriculumElement = curriculumService.getCurriculumElement(new CurriculumElementRefImpl(curriculumElementKey)); if(curriculumElement == null) { diff --git a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java index a8371cb259276b3da52e2b4bbe1c92c1ba11525a..e649932c395a0b5767b7e2ae96dc75d1d67cc4a9 100644 --- a/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java +++ b/src/main/java/org/olat/modules/curriculum/restapi/CurriculumsWebService.java @@ -214,6 +214,9 @@ public class CurriculumsWebService { @Context HttpServletRequest httpRequest) { CurriculumService curriculumService = CoreSpringFactory.getImpl(CurriculumService.class); Curriculum curriculum = curriculumService.getCurriculum(new CurriculumRefImpl(curriculumKey)); + if(curriculum == null) { + throw new WebApplicationException(Status.NOT_FOUND); + } allowedOrganisation(curriculum.getOrganisation(), getRoles(httpRequest)); return new CurriculumElementsWebService(curriculum); } diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties index db98364acf92e58dafec1f5776c3cd48a282c05f..f46efc3fea41e76fc2565a98318704022e7567e2 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties @@ -10,7 +10,8 @@ admin.description=Curriculum Konfiguration admin.menu.title=Curriculum admin.menu.title.alt=Curriculum admin.title=$\:admin.menu.title -coach=Betreuer +role.coach=Betreuer +role.curriculummanager=Curriculumverwalter confirm.delete.element.type.sucessfull=Der Typ "{0}" wurde erfolgreich gel\u00F6scht. confirmation.delete.type=Wollen Sie wirklich den Typ "{0}" l\u00F6schen? confirmation.delete.type.title=Typ "{0}" l\u00F6schen @@ -35,8 +36,8 @@ details.copy=Kopieren details.delete=L\u00F6schen info.copy.element.type.sucessfull=Der Typ "{0}" wurde erfolgreich kopiert. move.element=Element schieben -owner=Kursbesitzer -participant=Teilnehmer +role.owner=Kursbesitzer +role.participant=Teilnehmer remove.memberships=Entfernen resources.add=$add.resources resources.add.title= diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties index 6634e7267d11a7b77684a2b9fc5e15b28a145a9e..1a204932b748788a4b7caed76ad13983e7ecb8d5 100644 --- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties @@ -10,7 +10,8 @@ admin.description=Curriculum configuration admin.menu.title=Curriculum admin.menu.title.alt=Curriculum admin.title=$\:admin.menu.title -coach=Coach +role.coach=Coach +role.curriculummanager=Curriculum manager confirm.delete.element.type.sucessfull=The type "{0}" was successfully deleted. confirmation.delete.type=Do you really want to delete this type "{0}"? confirmation.delete.type.title=Delete type "{0}" @@ -35,8 +36,8 @@ details.copy=Copy details.delete=Delete info.copy.element.type.sucessfull=The type "{0}" was successfully copied. move.element=Move element -owner=Course owner -participant=Participant +role.owner=Course owner +role.participant=Participant remove.memberships=Remove resources.add=$add.resources supervisor=Fachvorsteher (supervisor) diff --git a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java index b14a12fd5d9db09a4be0097155048853d127445a..d2a71d8a720ff8f4d52f57fcc19f050135dbc37d 100644 --- a/src/main/java/org/olat/user/restapi/OrganisationsWebService.java +++ b/src/main/java/org/olat/user/restapi/OrganisationsWebService.java @@ -21,10 +21,12 @@ package org.olat.user.restapi; import static org.olat.restapi.security.RestSecurityHelper.isAdmin; +import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -36,13 +38,16 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.OrganisationManagedFlag; +import org.olat.basesecurity.OrganisationRoles; import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.OrganisationType; import org.olat.basesecurity.model.OrganisationRefImpl; import org.olat.basesecurity.model.OrganisationTypeRefImpl; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; import org.olat.core.id.Organisation; /** @@ -201,7 +206,8 @@ public class OrganisationsWebService { @Path("{organisationKey}") @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) - public Response postOrganisation(@PathParam("organisationKey") Long organisationKey, OrganisationVO organisation, @Context HttpServletRequest httpRequest) { + public Response postOrganisation(@PathParam("organisationKey") Long organisationKey, OrganisationVO organisation, + @Context HttpServletRequest httpRequest) { boolean isSystemAdministrator = isAdmin(httpRequest); if(!isSystemAdministrator) { return Response.serverError().status(Status.UNAUTHORIZED).build(); @@ -264,6 +270,200 @@ public class OrganisationsWebService { return new OrganisationTypesWebService(); } + /** + * Get all members of the specified organisation with the specified role. + * + * @response.representation.200.qname {http://www.example.com}userVO + * @response.representation.200.mediaType application/xml, application/json + * @response.representation.200.doc The array of members + * @response.representation.200.example {@link org.olat.user.restapi.Examples#SAMPLE_USERVOes} + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The organisation was not found + * @response.representation.409.doc The rolle is not valid + * @param httpRequest The HTTP request + * @return It returns an array of <code>UserVO</code> + */ + @GET + @Path("{organisationKey}/{role}") + public Response getMembers(@PathParam("organisationKey") Long organisationKey, @PathParam("role") String role, + @Context HttpServletRequest httpRequest) { + boolean isSystemAdministrator = isAdmin(httpRequest); + if(!isSystemAdministrator) { + return Response.serverError().status(Status.UNAUTHORIZED).build(); + } + return getMembers(organisationKey, getRoles(role)); + } + + private Response getMembers(Long organisationKey, OrganisationRoles role) { + OrganisationService organisationService = CoreSpringFactory.getImpl(OrganisationService.class); + + Organisation organisation = organisationService.getOrganisation(new OrganisationRefImpl(organisationKey)); + if(organisation == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + if(role == null) { + return Response.serverError().status(Status.CONFLICT).build(); + } + + List<Identity> members = organisationService.getMembersIdentity(organisation, role); + List<UserVO> voList = new ArrayList<>(members.size()); + for(Identity member:members) { + voList.add(UserVOFactory.get(member)); + } + return Response.ok(voList.toArray(new UserVO[voList.size()])).build(); + } + + /** + * Make the specified user a member of the specified organization + * with the specified role. + * + * @response.representation.200.doc The membership was added + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The organization or the identity was not found + * @param organisationKey The organization primary key + * @param role The role + * @param identityKey The member to make a coach of + * @param httpRequest The HTTP request + * @return Nothing + */ + @PUT + @Path("{organisationKey}/{role}/{identityKey}") + public Response putMember(@PathParam("organisationKey") Long organisationKey, @PathParam("role") String role, + @PathParam("identityKey") Long identityKey, @Context HttpServletRequest httpRequest) { + boolean isSystemAdministrator = isAdmin(httpRequest); + if(!isSystemAdministrator) { + return Response.serverError().status(Status.UNAUTHORIZED).build(); + } + return putMember(organisationKey, identityKey, getRoles(role)); + } + + private Response putMember(Long organisationKey, Long identityKey, OrganisationRoles role) { + OrganisationService organisationService = CoreSpringFactory.getImpl(OrganisationService.class); + Organisation organisation = organisationService.getOrganisation(new OrganisationRefImpl(organisationKey)); + if(organisation == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + if(role == null) { + return Response.serverError().status(Status.CONFLICT).build(); + } + + BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + Identity identity = securityManager.loadIdentityByKey(identityKey); + if(identity == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + + organisationService.addMember(organisation, identity, role); + return Response.ok().build(); + } + + /** + * Add a membership to the specified curriculum element. + * + * @response.representation.qname {http://www.example.com}curriculumElementMemberVO + * @response.representation.mediaType application/xml, application/json + * @response.representation.doc The curriculum element membership to persist + * @response.representation.example {@link org.olat.modules.curriculum.restapi.Examples#SAMPLE_CURRICULUMELEMENTMEMBERVO} + * @response.representation.200.doc The membership was persisted + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The curriculum element or the identity was not found + * @response.representation.409.doc The role is not allowed + * @param organisationKey The curriculum element primary key + * @param role The membership informations + * @return Nothing + */ + @PUT + @Path("{organisationKey}/{role}") + public Response putMembers(@PathParam("organisationKey") Long organisationKey, @PathParam("role") String role, + UserVO[] members, @Context HttpServletRequest httpRequest) { + boolean isSystemAdministrator = isAdmin(httpRequest); + if(!isSystemAdministrator) { + return Response.serverError().status(Status.UNAUTHORIZED).build(); + } + + OrganisationService organisationService = CoreSpringFactory.getImpl(OrganisationService.class); + Organisation organisation = organisationService.getOrganisation(new OrganisationRefImpl(organisationKey)); + if(organisation == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + + if(getRoles(role) == null) { + return Response.serverError().status(Status.CONFLICT).build(); + } + + BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + for(UserVO member:members) { + Identity identity = securityManager.loadIdentityByKey(member.getKey()); + if(identity != null) { + organisationService.addMember(organisation, identity, getRoles(role)); + } + } + return Response.ok().build(); + } + + /** + * Remove the membership of the identity from the specified organization and role. + * + * @response.representation.200.doc The membership was removed + * @response.representation.401.doc The roles of the authenticated user are not sufficient + * @response.representation.404.doc The organization or the identity was not found + * @param curriculumElementKey The curriculum element primary key + * @param identityKey The member to remove + * @return Nothing + */ + @DELETE + @Path("{organisationKey}/{role}/{identityKey}") + public Response deleteMember(@PathParam("organisationKey") Long organisationKey, @PathParam("role") String role, + @PathParam("identityKey") Long identityKey, @Context HttpServletRequest httpRequest) { + boolean isSystemAdministrator = isAdmin(httpRequest); + if(!isSystemAdministrator) { + return Response.serverError().status(Status.UNAUTHORIZED).build(); + } + return deleteMember(organisationKey, identityKey, getRoles(role)); + } + + private Response deleteMember(Long organisationKey, Long identityKey, OrganisationRoles role) { + OrganisationService organisationService = CoreSpringFactory.getImpl(OrganisationService.class); + Organisation organisation = organisationService.getOrganisation(new OrganisationRefImpl(organisationKey)); + if(organisation == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + if(role == null) { + return Response.serverError().status(Status.CONFLICT).build(); + } + + BaseSecurity securityManager = CoreSpringFactory.getImpl(BaseSecurity.class); + Identity identity = securityManager.loadIdentityByKey(identityKey); + if(identity == null) { + return Response.serverError().status(Status.NOT_FOUND).build(); + } + + organisationService.removeMember(organisation, identity, role); + return Response.ok().build(); + } + + /** + * Convert beautified role to enum. + * + * @param role + * @return The role enum or null + */ + private OrganisationRoles getRoles(String role) { + if(OrganisationRoles.isValue(role)) { + return OrganisationRoles.valueOf(role); + } else if("coaches".equals(role)) { + return OrganisationRoles.coach; + } + + if(role.endsWith("s")) { + role = role.substring(0, role.length() - 1); + } + if(OrganisationRoles.isValue(role)) { + return OrganisationRoles.valueOf(role); + } + return null; + } + private OrganisationVO[] toArrayOfVOes(List<Organisation> organisations) { int i=0; diff --git a/src/main/java/org/olat/user/ui/organisation/RoleListController.java b/src/main/java/org/olat/user/ui/organisation/RoleListController.java index a8005a306c1dbf201d8ef2ff69c63aabac75161b..cd9e73ed3243946deb2a388628b8227b1d735807 100644 --- a/src/main/java/org/olat/user/ui/organisation/RoleListController.java +++ b/src/main/java/org/olat/user/ui/organisation/RoleListController.java @@ -56,7 +56,7 @@ public class RoleListController extends BasicController { } private Link addLink(OrganisationRoles role, List<String> links) { - Link link = LinkFactory.createLink(role.name(), role.name(), getTranslator(), mainVC, this, Link.LINK); + Link link = LinkFactory.createLink("role." + role.name(), role.name(), getTranslator(), mainVC, this, Link.LINK); link.setUserObject(role); mainVC.put(role.name(), link); links.add(role.name()); diff --git a/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_de.properties index cae64a39b8cf6cfb9ba0a42474af607c74f9462f..8d39503c354efda7b7d42ecf2eb2d50e1c1b26f5 100644 --- a/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_de.properties @@ -6,20 +6,22 @@ add.root.type=Organisationtyp erstellen admin.description=Organisationen verwalten admin.menu.title=Organisationen admin.menu.title.alt=Organisationen -administrator=Administrator -author=Author -coach=Betreuer +role.administrator=Administrator +role.author=Author +role.coach=Betreuer +role.curriculummanager=Curriculumverwalter confirm.remove.text=Wollen Sie wirklich diese Benutzer ihre Mitgliedschaft entfernen? confirm.remove.title=Mitglieder entfernen create.organisation=Neue Organisation erstellen -curriculummanager=Curriculumverwalter +role.curriculummanager=Curriculumverwalter edit.type=Organisationtyp editieren -groupmanager=Gruppenverwalter -guest=Gast +role.groupmanager=Gruppenverwalter +role.guest=Gast +role.principal=Principal institution.to.org=Ressourceverwaltung mit Institutionname zu Organisationen migrieren institution.to.org.explain=Erkl\u00E4rung institution.to.org.label=Migration -learnresourcemanager=Lernressourcenverwalter +role.learnresourcemanager=Lernressourcenverwalter migrate=Migrieren move.organisation=Organisation schieben organisation.admin.enabled=Organisationen einschalten @@ -34,9 +36,9 @@ organisation.structure=Organisationenstruktur organisation.type=Organisationtyp organisation.types=Organisationentypen organisation.user.management=Benutzerverwaltung -poolmanager=Poolverwalter +role.poolmanager=Poolverwalter remove.memberships=Entfernen -sysadmin=Systemadministrator +role.sysadmin=Systemadministrator table.header.displayName=Name table.header.edit=Editieren table.header.identifier=Org. ID @@ -57,7 +59,7 @@ type.cssClass=CSS Class type.description=Beschreibung type.displayname=Name type.identifier=Bezeichnung -user=Benutzer -usermanager=Benutzerverwalter +role.user=Benutzer +role.usermanager=Benutzerverwalter warning.atleastone.member=Sie m\u00FCssen mindestens ein Benutzer w\u00E4hlen. warning.organisation.deleted=Die Organisation wurde seit kurzem gel\u00F6scht. diff --git a/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_en.properties index 6bbb8cf4a7fbf9ca4af2d0547fcc86ad4cc230ad..97b79faebc55682e2b0c9008996d469323b3fc22 100644 --- a/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/user/ui/organisation/_i18n/LocalStrings_en.properties @@ -6,20 +6,22 @@ add.root.type=Create organisation type admin.description=Manage your organisations admin.menu.title=Organisations admin.menu.title.alt=Organisations -administrator=Administrator -author=Author -coach=Coach +role.administrator=Administrator +role.author=Author +role.coach=Coach +role.curriculummanager=Curriculum manager confirm.remove.text=Do you really want to remove the memberships of this user? confirm.remove.title=Remove membership create.organisation=Create new organisation -curriculummanager=Curriculum manager +role.curriculummanager=Curriculum manager edit.type=Edit organisation type -groupmanager=Group manager -guest=Guest +role.groupmanager=Group manager +role.guest=Guest +role.principal=Principal institution.to.org=Migrate learn resource management by institution name to organisation institution.to.org.explain=Explanation institution.to.org.label=Migration -learnresourcemanager=Learn resource manager +role.learnresourcemanager=Learn resource manager migrate=Migrate move.organisation=Move organisation organisation.admin.enabled=Enable organisations @@ -34,9 +36,9 @@ organisation.structure=Organisations structures organisation.type=Organisation type organisation.types=Organisations types organisation.user.management=User management -poolmanager=Question bank manager +role.poolmanager=Question bank manager remove.memberships=Remove -sysadmin=System administrator +role.sysadmin=System administrator table.header.displayName=Name table.header.edit=Edit table.header.identifier=Org. ID @@ -57,7 +59,7 @@ type.cssClass=CSS class type.description=Description type.displayname=Name type.identifier=Identifier -user=User -usermanager=User manager +role.user=User +role.usermanager=User manager warning.atleastone.member=You need to select at least one user. warning.organisation.deleted=The organisation was deleted. diff --git a/src/main/java/org/olat/user/ui/organisation/component/RoleFlexiCellRenderer.java b/src/main/java/org/olat/user/ui/organisation/component/RoleFlexiCellRenderer.java index e3077c88c8c9cc439f186bda4420748608d4eb3e..6bbc11551ebb8ef473403af7bd87a17d2c90f3d7 100644 --- a/src/main/java/org/olat/user/ui/organisation/component/RoleFlexiCellRenderer.java +++ b/src/main/java/org/olat/user/ui/organisation/component/RoleFlexiCellRenderer.java @@ -47,11 +47,11 @@ public class RoleFlexiCellRenderer implements FlexiCellRenderer { URLBuilder ubu, Translator trans) { if(cellValue instanceof OrganisationRoles) { OrganisationRoles role = (OrganisationRoles)cellValue; - target.append(translator.translate(role.name())); + target.append(translator.translate("role.".concat(role.name()))); } else if(cellValue instanceof String) { String val = (String)cellValue; if(OrganisationRoles.valid(val)) { - target.append(translator.translate(OrganisationRoles.valueOf(val).name())); + target.append(translator.translate("role.".concat(OrganisationRoles.valueOf(val).name()))); } else { target.append(StringHelper.escapeHtml(val)); } diff --git a/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java b/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java index 39ba217d771d6e05f423c1d1079595c91d20c351..673124fba10a9efca345d23410e17b53f7825743 100644 --- a/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java +++ b/src/test/java/org/olat/modules/curriculum/manager/CurriculumElementDAOTest.java @@ -225,7 +225,7 @@ public class CurriculumElementDAOTest extends OlatTestCase { Identity supervisor = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-supervisor-1"); Curriculum curriculum = curriculumService.createCurriculum("cur-for-el-4", "Curriculum for element", "Curriculum", null); CurriculumElement element = curriculumService.createCurriculumElement("Element-4", "4. Element", null, null, null, null, curriculum); - curriculumService.addMember(element, supervisor, CurriculumRoles.supervisor); + curriculumService.addMember(element, supervisor, CurriculumRoles.curriculummanager); dbInstance.commitAndCloseSession(); List<CurriculumElementMember> members = curriculumElementDao.getMembers(element); @@ -233,7 +233,7 @@ public class CurriculumElementDAOTest extends OlatTestCase { Assert.assertEquals(1, members.size()); CurriculumElementMember member = members.get(0); Assert.assertEquals(supervisor, member.getIdentity()); - Assert.assertEquals(CurriculumRoles.supervisor.name(), member.getRole()); + Assert.assertEquals(CurriculumRoles.curriculummanager.name(), member.getRole()); } @Test @@ -241,10 +241,10 @@ public class CurriculumElementDAOTest extends OlatTestCase { Identity supervisor = JunitTestHelper.createAndPersistIdentityAsRndUser("cur-supervisor-1"); Curriculum curriculum = curriculumService.createCurriculum("cur-for-el-4", "Curriculum for element", "Curriculum", null); CurriculumElement element = curriculumService.createCurriculumElement("Element-4", "4. Element", null, null, null, null, curriculum); - curriculumService.addMember(element, supervisor, CurriculumRoles.supervisor); + curriculumService.addMember(element, supervisor, CurriculumRoles.curriculummanager); dbInstance.commitAndCloseSession(); - List<Identity> members = curriculumElementDao.getMembersIdentity(element, CurriculumRoles.supervisor.name()); + List<Identity> members = curriculumElementDao.getMembersIdentity(element, CurriculumRoles.curriculummanager.name()); Assert.assertNotNull(members); Assert.assertEquals(1, members.size()); Assert.assertEquals(supervisor, members.get(0)); diff --git a/src/test/java/org/olat/restapi/CurriculumElementsWebServiceTest.java b/src/test/java/org/olat/restapi/CurriculumElementsWebServiceTest.java index daf0b1b016d1199183bc02d7f219ad77f31d057f..466ea2acdfc2f939a810ec8af3ecacac6aa6bb9c 100644 --- a/src/test/java/org/olat/restapi/CurriculumElementsWebServiceTest.java +++ b/src/test/java/org/olat/restapi/CurriculumElementsWebServiceTest.java @@ -477,6 +477,34 @@ public class CurriculumElementsWebServiceTest extends OlatJerseyTestCase { Assert.assertEquals(member.getKey(), memberVoes.get(0).getKey()); } + @Test + public void getUsers_curriculumManagers() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("element-member-6"); + Organisation organisation = organisationService.createOrganisation("REST Parent Organisation 8", "REST-p-8-organisation", "", null, null); + Curriculum curriculum = curriculumService.createCurriculum("REST-Curriculum-elements", "REST Curriculum", "A curriculum accessible by REST API for elemets", organisation); + CurriculumElement element = curriculumService.createCurriculumElement("Element-14", "Element 14", null, null, null, null, curriculum); + dbInstance.commit(); + + curriculumService.addMember(element, member, CurriculumRoles.curriculummanager); + dbInstance.commitAndCloseSession(); + + URI request = UriBuilder.fromUri(getContextURI()).path("curriculum").path(curriculum.getKey().toString()) + .path("elements").path(element.getKey().toString()).path("users").queryParam("role", "curriculummanager").build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<UserVO> memberVoes = parseUserArray(response.getEntity()); + + Assert.assertNotNull(memberVoes); + Assert.assertEquals(1, memberVoes.size()); + Assert.assertEquals(member.getKey(), memberVoes.get(0).getKey()); + } + @Test public void getParticipants() throws IOException, URISyntaxException { @@ -533,6 +561,34 @@ public class CurriculumElementsWebServiceTest extends OlatJerseyTestCase { Assert.assertEquals(member.getKey(), memberVoes.get(0).getKey()); } + @Test + public void getCurriculumManagers() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("element-member-10"); + Organisation organisation = organisationService.createOrganisation("REST Parent Organisation 10", "REST-p-10-organisation", "", null, null); + Curriculum curriculum = curriculumService.createCurriculum("REST-Curriculum-elements", "REST Curriculum", "A curriculum accessible by REST API for elemets", organisation); + CurriculumElement element = curriculumService.createCurriculumElement("Element-16", "Element 16", null, null, null, null, curriculum); + dbInstance.commit(); + + curriculumService.addMember(element, member, CurriculumRoles.curriculummanager); + dbInstance.commitAndCloseSession(); + + URI request = UriBuilder.fromUri(getContextURI()).path("curriculum").path(curriculum.getKey().toString()) + .path("elements").path(element.getKey().toString()).path("curriculummanagers").build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<UserVO> memberVoes = parseUserArray(response.getEntity()); + + Assert.assertNotNull(memberVoes); + Assert.assertEquals(1, memberVoes.size()); + Assert.assertEquals(member.getKey(), memberVoes.get(0).getKey()); + } + @Test public void addMembership() throws IOException, URISyntaxException { diff --git a/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java b/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java index 16de3bb799f79a16c3be813a100a45d576e8acb5..b147fe14ab83d215fb7bc4bb937272debdaafac5 100644 --- a/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java +++ b/src/test/java/org/olat/restapi/OrganisationsWebServiceTest.java @@ -30,23 +30,31 @@ import java.util.List; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriBuilder; +import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; +import org.apache.http.util.EntityUtils; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import org.olat.basesecurity.OrganisationManagedFlag; +import org.olat.basesecurity.OrganisationRoles; import org.olat.basesecurity.OrganisationService; import org.olat.basesecurity.OrganisationType; import org.olat.basesecurity.model.OrganisationRefImpl; import org.olat.core.commons.persistence.DB; +import org.olat.core.id.Identity; import org.olat.core.id.Organisation; +import org.olat.test.JunitTestHelper; import org.olat.test.OlatJerseyTestCase; import org.olat.user.restapi.OrganisationVO; +import org.olat.user.restapi.UserVO; +import org.olat.user.restapi.UserVOFactory; import org.springframework.beans.factory.annotation.Autowired; /** @@ -304,7 +312,117 @@ public class OrganisationsWebServiceTest extends OlatJerseyTestCase { Assert.assertEquals(parentOrganisation, savedOrganisation.getRoot()); } + @Test + public void getMembers_users() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-11"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 5", "REST-p-5-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.user); + dbInstance.commit(); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path(organisation.getKey().toString()) + .path("users").build(); + HttpGet method = conn.createGet(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + List<UserVO> users = parseUserArray(response.getEntity()); + Assert.assertNotNull(users); + Assert.assertEquals(1, users.size()); + Assert.assertEquals(member.getKey(), users.get(0).getKey()); + } + @Test + public void addMember_principal() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-12"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 6", "REST-p-6-organisation", "", null, null); + dbInstance.commit(); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path(organisation.getKey().toString()) + .path("principals").path(member.getKey().toString()).build(); + HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + EntityUtils.consume(response.getEntity()); + + List<Identity> principals = organisationService.getMembersIdentity(organisation, OrganisationRoles.principal); + Assert.assertNotNull(principals); + Assert.assertEquals(1, principals.size()); + Assert.assertEquals(member, principals.get(0)); + } + + @Test + public void addMembers_author() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity author1 = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-14"); + Identity author2 = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-15"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 7", "REST-p-7-organisation", "", null, null); + dbInstance.commit(); + + + UserVO[] authors = new UserVO[] { + UserVOFactory.get(author1), + UserVOFactory.get(author2) + }; + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path(organisation.getKey().toString()) + .path("authors").build(); + HttpPut method = conn.createPut(request, MediaType.APPLICATION_JSON, true); + conn.addJsonEntity(method, authors); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + EntityUtils.consume(response.getEntity()); + + List<Identity> authorList = organisationService.getMembersIdentity(organisation, OrganisationRoles.author); + Assert.assertNotNull(authorList); + Assert.assertEquals(2, authorList.size()); + } + + + @Test + public void removeMember_administrator() + throws IOException, URISyntaxException { + RestConnection conn = new RestConnection(); + assertTrue(conn.login("administrator", "openolat")); + + Identity member = JunitTestHelper.createAndPersistIdentityAsRndUser("org-member-13"); + Organisation organisation = organisationService.createOrganisation("REST Organisation 7", "REST-p-7-organisation", "", null, null); + organisationService.addMember(organisation, member, OrganisationRoles.administrator); + dbInstance.commit(); + + URI request = UriBuilder.fromUri(getContextURI()).path("organisations").path(organisation.getKey().toString()) + .path("administrators").path(member.getKey().toString()).build(); + HttpDelete method = conn.createDelete(request, MediaType.APPLICATION_JSON); + + HttpResponse response = conn.execute(method); + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); + EntityUtils.consume(response.getEntity()); + + List<Identity> administators = organisationService.getMembersIdentity(organisation, OrganisationRoles.administrator); + Assert.assertNotNull(administators); + Assert.assertTrue(administators.isEmpty()); + } + + protected List<UserVO> parseUserArray(HttpEntity entity) { + try(InputStream in=entity.getContent()) { + ObjectMapper mapper = new ObjectMapper(jsonFactory); + return mapper.readValue(in, new TypeReference<List<UserVO>>(){/* */}); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } protected List<OrganisationVO> parseOrganisationArray(InputStream body) { try {