/* * Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK * MISO project contacts: Robert Davey, Mario Caccamo @ TGAC * ********************************************************************* * * This file is part of MISO. * * MISO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MISO 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 MISO. If not, see <http://www.gnu.org/licenses/>. * * ********************************************************************* */ package uk.ac.bbsrc.tgac.miso.webapp.controller; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.support.SessionStatus; import org.springframework.web.servlet.ModelAndView; import com.eaglegenomics.simlims.core.Activity; import com.eaglegenomics.simlims.core.Group; import com.eaglegenomics.simlims.core.Protocol; import com.eaglegenomics.simlims.core.User; import com.eaglegenomics.simlims.core.manager.ProtocolManager; import com.eaglegenomics.simlims.core.manager.SecurityManager; import uk.ac.bbsrc.tgac.miso.core.data.impl.UserImpl; import uk.ac.bbsrc.tgac.miso.core.factory.DataObjectFactory; import uk.ac.bbsrc.tgac.miso.core.security.PasswordCodecService; import uk.ac.bbsrc.tgac.miso.core.util.LimsUtils; import javax.servlet.http.HttpServletRequest; @Controller @SessionAttributes("user") public class EditUserController { protected static final Logger log = LoggerFactory.getLogger(EditUserController.class); @Autowired private SecurityManager securityManager; @Autowired private PasswordCodecService passwordCodecService; @Autowired private ProtocolManager protocolManager; @Autowired private DataObjectFactory dataObjectFactory; public void setDataObjectFactory(DataObjectFactory dataObjectFactory) { this.dataObjectFactory = dataObjectFactory; } public void setProtocolManager(ProtocolManager protocolManager) { this.protocolManager = protocolManager; } public void setSecurityManager(SecurityManager securityManager) { this.securityManager = securityManager; } public void setPasswordCodecService(PasswordCodecService passwordCodecService) { this.passwordCodecService = passwordCodecService; } @ModelAttribute("groups") public Collection<Group> populateGroups() throws IOException { try { List<Group> groups = new ArrayList<Group>(securityManager.listAllGroups()); Collections.sort(groups); return groups; } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to list groups", ex); } throw ex; } } @ModelAttribute("roles") public Collection<String> populateRoles() throws IOException { try { Collection<String> roles = new ArrayList<String>(); for (Protocol protocol : protocolManager.listAllProtocols()) { roles.add(protocol.getRole()); } for (Activity activity : protocolManager.listAllActivities()) { roles.add(activity.getRole()); } return roles; } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to list roles", ex); } throw ex; } } @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET) public ModelAndView userForm(@PathVariable Long userId, ModelMap model, HttpServletRequest request) throws SecurityException, IOException { try { User user = securityManager.getUserById(userId); if (user != null) { if (SecurityContextHolder.getContext().getAuthentication().getName().equals(user.getLoginName())) { model.put("user", user); String securityMethod = (String)request.getSession().getServletContext().getAttribute("security.method"); model.put("securityMethod", securityMethod); return new ModelAndView("/pages/editUser.jsp", model); } else { throw new SecurityException("You can only edit your own user details."); } } else { throw new IOException("No such user"); } } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to show user", ex); } throw ex; } } @RequestMapping(value = "/admin/user/new", method = RequestMethod.GET) public ModelAndView newSetupForm(ModelMap model, HttpServletRequest request) throws IOException { String securityMethod = (String)request.getSession().getServletContext().getAttribute("security.method"); if ("ldap".equals(securityMethod)) { throw new IOException("Cannot add users through the MISO interface for LDAP-managed security. Please add the LDAP user then log in as normal."); } else { return adminSetupForm(UserImpl.UNSAVED_ID, model, request); } } @RequestMapping(value = "/admin/user/{userId}", method = RequestMethod.GET) public ModelAndView adminSetupForm(@PathVariable Long userId, ModelMap model, HttpServletRequest request) throws IOException { try { model.put("user", userId == UserImpl.UNSAVED_ID ? dataObjectFactory.getUser() : securityManager.getUserById(userId)); String securityMethod = (String)request.getSession().getServletContext().getAttribute("security.method"); model.put("securityMethod", securityMethod); return new ModelAndView("/pages/editUser.jsp", model); } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to show user", ex); } throw ex; } } @RequestMapping(value = "/admin/user", method = RequestMethod.POST) public String adminProcessSubmit(@ModelAttribute("user") User user, ModelMap model, SessionStatus session, HttpServletRequest request) throws IOException { try { if (user.getUserId() == UserImpl.UNSAVED_ID) { //new user. don't require a password to be set initially if (!LimsUtils.isStringEmptyOrNull(request.getParameter("newpassword")) && !LimsUtils.isStringEmptyOrNull(request.getParameter("confirmpassword"))) { if (request.getParameter("newpassword").equals(request.getParameter("confirmpassword"))) { if (!"".equals(request.getParameter("newpassword")) && !"".equals(request.getParameter("confirmpassword"))) { if (SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(new GrantedAuthorityImpl("ROLE_ADMIN"))) { //auth'ed user is the account holder or an admin log.info("Admin '"+SecurityContextHolder.getContext().getAuthentication().getName()+"' attempting user password change for user '"+user.getLoginName()+"'"); user.setPassword(request.getParameter("newpassword")); } else { throw new IOException("Cannot create user - user isn't an admin."); } } else { throw new IOException("New password cannot be empty"); } } else { throw new IOException("New password and confirmation don't match."); } } } else { if (!LimsUtils.isStringEmptyOrNull(request.getParameter("password")) && !LimsUtils.isStringEmptyOrNull(request.getParameter("newpassword"))) { if (!LimsUtils.isStringEmptyOrNull(request.getParameter("confirmpassword"))) { if (request.getParameter("newpassword").equals(request.getParameter("confirmpassword"))) { if (!"".equals(request.getParameter("newpassword")) && !"".equals(request.getParameter("confirmpassword"))) { if (SecurityContextHolder.getContext().getAuthentication().getName().equals(user.getLoginName())) { if (passwordCodecService.getEncoder().isPasswordValid(user.getPassword(), request.getParameter("password"), null)) { log.debug("User '"+user.getLoginName()+"' attempting own password change"); user.setPassword(request.getParameter("newpassword")); } } else if (SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(new GrantedAuthorityImpl("ROLE_ADMIN"))) { //auth'ed user is the account holder or an admin log.info("Admin '"+SecurityContextHolder.getContext().getAuthentication().getName()+"' attempting user password change for user '"+user.getLoginName()+"'"); user.setPassword(request.getParameter("newpassword")); } else { throw new IOException("Cannot update user - existing password check failed, or user isn't an admin."); } } else { throw new IOException("New password cannot be empty"); } } else { throw new IOException("New password and confirmation don't match."); } } else { throw new IOException("You must supply a confirmation of your new password."); } } } securityManager.saveUser(user); session.setComplete(); model.clear(); return "redirect:/miso/admin/users"; } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to update user", ex); } throw ex; } } @RequestMapping(value = "/user", method = RequestMethod.POST) public String processSubmit(@ModelAttribute("user") User user, ModelMap model, SessionStatus session, HttpServletRequest request) throws IOException { try { if (!LimsUtils.isStringEmptyOrNull(request.getParameter("password")) && !LimsUtils.isStringEmptyOrNull(request.getParameter("newpassword"))) { if (!LimsUtils.isStringEmptyOrNull(request.getParameter("confirmpassword"))) { if (request.getParameter("newpassword").equals(request.getParameter("confirmpassword"))) { if (!"".equals(request.getParameter("newpassword")) && !"".equals(request.getParameter("confirmpassword"))) { if (SecurityContextHolder.getContext().getAuthentication().getName().equals(user.getLoginName())) { if (passwordCodecService.getEncoder().isPasswordValid(user.getPassword(), request.getParameter("password"), null)) { log.debug("User '"+user.getLoginName()+"' attempting own password change"); user.setPassword(request.getParameter("newpassword")); } } else { throw new IOException("Cannot update user - existing password check failed, or user isn't an admin."); } } else { throw new IOException("New password cannot be empty"); } } else { throw new IOException("New password and confirmation don't match."); } } else { throw new IOException("You must supply a confirmation of your new password."); } } securityManager.saveUser(user); session.setComplete(); model.clear(); return "redirect:/miso/myAccount"; } catch (IOException ex) { if (log.isDebugEnabled()) { log.debug("Failed to update user", ex); } throw ex; } } }