Index: lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java =================================================================== diff -u -r1d8de80be95ff1880654400834faa16a54bca41c -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java (.../CentralConstants.java) (revision 1d8de80be95ff1880654400834faa16a54bca41c) +++ lams_central/src/java/org/lamsfoundation/lams/util/CentralConstants.java (.../CentralConstants.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -70,6 +70,8 @@ public static final String PARAM_MONITOR_IDS = "monitorIds"; public static final String PARAM_CUSTOM_CSV = "customCSV"; + + public static final String PARAM_USER_ID = "userId"; public static final String METHOD_START = "start"; Index: lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java =================================================================== diff -u -r85ec7835f2f0019c7a7433787991e13939930f1d -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java (.../PedagogicalPlannerAction.java) (revision 85ec7835f2f0019c7a7433787991e13939930f1d) +++ lams_central/src/java/org/lamsfoundation/lams/web/planner/PedagogicalPlannerAction.java (.../PedagogicalPlannerAction.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -40,6 +40,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.Vector; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; @@ -93,6 +94,7 @@ import org.lamsfoundation.lams.learningdesign.service.ImportToolContentException; import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.monitoring.service.IMonitoringService; +import org.lamsfoundation.lams.planner.PedagogicalPlannerNodeRole; import org.lamsfoundation.lams.planner.PedagogicalPlannerSequenceNode; import org.lamsfoundation.lams.planner.dao.PedagogicalPlannerDAO; import org.lamsfoundation.lams.planner.dto.PedagogicalPlannerActivityDTO; @@ -134,6 +136,7 @@ * @struts:action path="/pedagogicalPlanner/grouping" scope="request" name="PedagogicalPlannerGroupingForm" * validate="false" parameter="method" * @struts:action-forward name="grouping" path="/pedagogical_planner/grouping.jsp" + * @struts:action-forward name="editAuthors" path="/pedagogical_planner/editAuthors.jsp" */ public class PedagogicalPlannerAction extends LamsDispatchAction { @@ -638,10 +641,6 @@ */ public ActionForward openSequenceNode(ActionMapping mapping, ActionForm form, HttpServletRequest request, Long nodeUid) throws ServletException { - // Only SysAdmin can open the editor - Boolean isSysAdmin = request.isUserInRole(Role.SYSADMIN); - Boolean edit = WebUtil.readBooleanParam(request, CentralConstants.PARAM_EDIT, false); - edit &= isSysAdmin; String filterText = WebUtil.readStrParam(request, CentralConstants.PARAM_FILTER_TEXT, true); // Do we display the root (top) node or an existing one PedagogicalPlannerSequenceNode node = null; @@ -652,6 +651,13 @@ } PedagogicalPlannerAction.log.debug("Opening sequence node with UID: " + nodeUid); + // Only certain roles can open the editor + User user = (User) getUserManagementService().getUserByLogin(request.getRemoteUser()); + Boolean hasRole = request.isUserInRole(Role.SYSADMIN) || getUserManagementService().isUserGlobalAuthorAdmin() + || getPedagogicalPlannerDAO().canUserWriteToNode(user.getUserId(), nodeUid, Role.ROLE_AUTHOR_ADMIN); + Boolean edit = WebUtil.readBooleanParam(request, CentralConstants.PARAM_EDIT, false); + edit &= hasRole; + // Fill the DTO PedagogicalPlannerSequenceNodeDTO dto = null; if (filterText != null) { @@ -698,7 +704,7 @@ Boolean importNode = WebUtil.readBooleanParam(request, CentralConstants.PARAM_IMPORT_NODE, false); dto.setCreateSubnode(createSubnode); dto.setEdit(edit); - dto.setIsSysAdmin(isSysAdmin); + dto.setHasRole(hasRole); dto.setImportNode(importNode); dto.setTitlePath(titlePath); @@ -1601,6 +1607,45 @@ writeOutFile(response, zipFilePath); return null; } + + public ActionForward editAuthors(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID, true); + + // TODO only sysadmin and author admins of the given (or parent) node can edit authors + + Integer orgId = getUserManagementService().getRootOrganisation().getOrganisationId(); + Vector potentialUsers = getUserManagementService().getUsersFromOrganisationByRole(orgId, Role.AUTHOR_ADMIN, false, true); + + List existingUsers = getPedagogicalPlannerDAO().getNodeUsers(nodeUid, Role.ROLE_AUTHOR_ADMIN); + + request.setAttribute("existingUsers", existingUsers); + request.setAttribute("potentialUsers", potentialUsers); + + return mapping.findForward("editAuthors"); + } + + public ActionForward addAuthor(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + Integer userId = WebUtil.readIntParam(request, CentralConstants.PARAM_USER_ID, false); + Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID, true); + + // TODO only sysadmin and author admin of given (or parent) node can add admin + + getPedagogicalPlannerDAO().saveNodeRole(userId, nodeUid, Role.ROLE_AUTHOR_ADMIN); + return null; + } + + public ActionForward removeAuthor(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + Integer userId = WebUtil.readIntParam(request, CentralConstants.PARAM_USER_ID, false); + Long nodeUid = WebUtil.readLongParam(request, CentralConstants.PARAM_UID, false); + + // TODO only sysadmin and author admin of given (or parent) node can remove admin + + getPedagogicalPlannerDAO().removeNodeRole(userId, nodeUid, Role.ROLE_AUTHOR_ADMIN); + return null; + } /*------------------------ COMMON METHODS --------------------*/ Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.hbm.xml =================================================================== diff -u --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.hbm.xml (revision 0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.hbm.xml (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040003.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040003.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch02040003.sql (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -0,0 +1,17 @@ +SET AUTOCOMMIT = 0; + +-- LDEV-2476 +CREATE TABLE lams_planner_node_role ( + uid BIGINT(20) NOT NULL AUTO_INCREMENT + , node_uid BIGINT(20) NOT NULL + , user_id BIGINT(20) NOT NULL + , role_id INT(6) NOT NULL + , PRIMARY KEY (uid) +)TYPE=InnoDB; + +ALTER TABLE lams_planner_node_role ADD CONSTRAINT FK_planner_node_role_user FOREIGN KEY (user_id) REFERENCES lams_user (user_id) ON DELETE CASCADE ON UPDATE NO ACTION; +ALTER TABLE lams_planner_node_role ADD CONSTRAINT FK_planner_node_role_node FOREIGN KEY (node_uid) REFERENCES lams_planner_nodes (uid) ON DELETE CASCADE ON UPDATE NO ACTION; +ALTER TABLE lams_planner_node_role ADD CONSTRAINT FK_planner_node_role_role FOREIGN KEY (role_id) REFERENCES lams_role (role_id) ON DELETE CASCADE ON UPDATE NO ACTION; + +COMMIT; +SET AUTOCOMMIT = 1; Index: lams_common/src/java/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/planner/PedagogicalPlannerNodeRole.java (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -0,0 +1,80 @@ +/**************************************************************** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +/* $Id$ */ +package org.lamsfoundation.lams.planner; + +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; + +public class PedagogicalPlannerNodeRole { + + Long uid; + PedagogicalPlannerSequenceNode node; + User user; + Role role; + + public PedagogicalPlannerNodeRole() { + + } + + public PedagogicalPlannerNodeRole(PedagogicalPlannerSequenceNode node, User user, Role role) { + super(); + this.node = node; + this.user = user; + this.role = role; + } + + public Long getUid() { + return uid; + } + + public void setUid(Long uid) { + this.uid = uid; + } + + public PedagogicalPlannerSequenceNode getNode() { + return node; + } + + public void setNode(PedagogicalPlannerSequenceNode node) { + this.node = node; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Role getRole() { + return role; + } + + public void setRole(Role role) { + this.role = role; + } + +} + \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/planner/dao/PedagogicalPlannerDAO.java =================================================================== diff -u -r9a28a1269fd337e431f26f8515bdc10bcf3a53ee -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_common/src/java/org/lamsfoundation/lams/planner/dao/PedagogicalPlannerDAO.java (.../PedagogicalPlannerDAO.java) (revision 9a28a1269fd337e431f26f8515bdc10bcf3a53ee) +++ lams_common/src/java/org/lamsfoundation/lams/planner/dao/PedagogicalPlannerDAO.java (.../PedagogicalPlannerDAO.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -41,4 +41,12 @@ Integer getNextOrderId(Long parentUid); PedagogicalPlannerSequenceNode getNeighbourNode(PedagogicalPlannerSequenceNode node, Integer orderDelta); + + Boolean canUserWriteToNode(Integer userId, Long nodeUid, Integer roleId); + + List getNodeUsers(Long nodeUid, Integer roleId); + + void saveNodeRole(Integer userId, Long nodeUid, Integer roleId); + + void removeNodeRole(Integer userId, Long nodeUid, Integer roleId); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/planner/dao/hibernate/PedagogicalPlannerDAOHibernate.java =================================================================== diff -u -r242af895b7cc36e5f825a4b99862b92a5faa87ed -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_common/src/java/org/lamsfoundation/lams/planner/dao/hibernate/PedagogicalPlannerDAOHibernate.java (.../PedagogicalPlannerDAOHibernate.java) (revision 242af895b7cc36e5f825a4b99862b92a5faa87ed) +++ lams_common/src/java/org/lamsfoundation/lams/planner/dao/hibernate/PedagogicalPlannerDAOHibernate.java (.../PedagogicalPlannerDAOHibernate.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -28,8 +28,11 @@ import java.util.List; import java.util.Set; +import org.lamsfoundation.lams.planner.PedagogicalPlannerNodeRole; import org.lamsfoundation.lams.planner.PedagogicalPlannerSequenceNode; import org.lamsfoundation.lams.planner.dao.PedagogicalPlannerDAO; +import org.lamsfoundation.lams.usermanagement.Role; +import org.lamsfoundation.lams.usermanagement.User; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** @@ -47,6 +50,10 @@ + PedagogicalPlannerSequenceNode.class.getName() + " AS n WHERE n.parent.uid=?"; private static final String FIND_NEIGHBOUR_NODE = "FROM " + PedagogicalPlannerSequenceNode.class.getName() + " AS n WHERE ((? IS NULL AND n.parent=NULL) OR n.parent.uid=?) AND n.order=?"; + private static final String GET_PLANNER_NODE_ROLE = "FROM " + PedagogicalPlannerNodeRole.class.getName() + + " WHERE user.userId=? AND node.uid=? AND role.roleId=?"; + private static final String GET_PLANNER_NODE_ROLE_USERS = "SELECT p.user FROM " + + PedagogicalPlannerNodeRole.class.getName() + " AS p WHERE p.node.uid=? AND p.role.roleId=?"; /* * private static final String FIND_RECENTLY_MODIFIED_LD = "SELECT ld FROM " + LearningDesign.class.getName() + " AS @@ -116,4 +123,37 @@ PedagogicalPlannerDAOHibernate.FIND_NEIGHBOUR_NODE, new Object[] { parentUid, parentUid, order }) .get(0); } + + private List getPlannerNodeRoles(Integer userId, Long nodeUid, Integer roleId) { + return getHibernateTemplate().find(PedagogicalPlannerDAOHibernate.GET_PLANNER_NODE_ROLE, + new Object[] { userId, nodeUid, roleId }); + } + + // TODO check parent nodes for inherited role + public Boolean canUserWriteToNode(Integer userId, Long nodeUid, Integer roleId) { + List l = getPlannerNodeRoles(userId, nodeUid, roleId); + return (l != null && l.size() > 0 ? true : false); + } + + public List getNodeUsers(Long nodeUid, Integer roleId) { + return getHibernateTemplate().find(PedagogicalPlannerDAOHibernate.GET_PLANNER_NODE_ROLE_USERS, + new Object[] { nodeUid, roleId }); + } + + public void saveNodeRole(Integer userId, Long nodeUid, Integer roleId) { + PedagogicalPlannerSequenceNode node = getByUid(nodeUid); + User user = (User) getHibernateTemplate().get(User.class, userId); + Role role = (Role) getHibernateTemplate().get(Role.class, roleId); + PedagogicalPlannerNodeRole nodeRole = new PedagogicalPlannerNodeRole(node, user, role); + getHibernateTemplate().saveOrUpdate(nodeRole); + getHibernateTemplate().flush(); + } + + public void removeNodeRole(Integer userId, Long nodeUid, Integer roleId) { + List l = getPlannerNodeRoles(userId, nodeUid, roleId); + for (Object o : l) { + getHibernateTemplate().delete(o); + } + getHibernateTemplate().flush(); + } } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/planner/dto/PedagogicalPlannerSequenceNodeDTO.java =================================================================== diff -u -racf8b8aad096f0fdc9b5beada47f7cb646b59aca -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_common/src/java/org/lamsfoundation/lams/planner/dto/PedagogicalPlannerSequenceNodeDTO.java (.../PedagogicalPlannerSequenceNodeDTO.java) (revision acf8b8aad096f0fdc9b5beada47f7cb646b59aca) +++ lams_common/src/java/org/lamsfoundation/lams/planner/dto/PedagogicalPlannerSequenceNodeDTO.java (.../PedagogicalPlannerSequenceNodeDTO.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -46,7 +46,7 @@ // Not node-bound variables, but simply attributes used in JSP page private Boolean edit = false; private Boolean createSubnode = false; - private Boolean isSysAdmin = true; + private Boolean hasRole = true; private Boolean importNode = false; // for the list on the main screen private List recentlyModifiedNodes; @@ -172,12 +172,12 @@ this.createSubnode = createSubnode; } - public Boolean getIsSysAdmin() { - return isSysAdmin; + public Boolean getHasRole() { + return hasRole; } - public void setIsSysAdmin(Boolean isSysAdmin) { - this.isSysAdmin = isSysAdmin; + public void setHasRole(Boolean hasRole) { + this.hasRole = hasRole; } public Boolean getImportNode() { Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java =================================================================== diff -u -r7998a31f6d7d4f1eef3e866bafef22caa012eb7a -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision 7998a31f6d7d4f1eef3e866bafef22caa012eb7a) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -375,6 +375,12 @@ public boolean isUserGlobalGroupAdmin(); /** + * Return true if user is a global author admin. + * @return + */ + public boolean isUserGlobalAuthorAdmin(); + + /** * Return true if user has sysadmin role in root organisation. * @return */ Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -r9c7d0817bb20458f827a11ac66836dc2530242f9 -r3a1ae19ae51ede32cec920fc9bb07f6787f562ff --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 9c7d0817bb20458f827a11ac66836dc2530242f9) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 3a1ae19ae51ede32cec920fc9bb07f6787f562ff) @@ -1017,6 +1017,12 @@ Integer requestorId = getRequestorId(); return requestorId != null ? isUserInRole(requestorId, rootOrgId, Role.GROUP_ADMIN) : false; } + + public boolean isUserGlobalAuthorAdmin() { + Integer rootOrgId = getRootOrganisation().getOrganisationId(); + Integer requestorId = getRequestorId(); + return requestorId != null ? isUserInRole(requestorId, rootOrgId, Role.AUTHOR_ADMIN) : false; + } public boolean isUserSysAdmin() { Integer rootOrgId = getRootOrganisation().getOrganisationId();