/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.web.controller.user; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Vector; import javax.servlet.http.HttpSession; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.Person; import org.openmrs.PersonName; import org.openmrs.Role; import org.openmrs.User; import org.openmrs.api.PasswordException; import org.openmrs.api.UserService; import org.openmrs.api.context.Context; import org.openmrs.messagesource.MessageSourceService; import org.openmrs.propertyeditor.RoleEditor; import org.openmrs.util.OpenmrsConstants; import org.openmrs.util.OpenmrsUtil; import org.openmrs.validator.UserValidator; import org.openmrs.web.WebConstants; import org.openmrs.web.user.UserProperties; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.util.StringUtils; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.request.WebRequest; /** * Used for creating/editing User */ @Controller public class UserFormController { protected static final Log log = LogFactory.getLog(UserFormController.class); @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Role.class, new RoleEditor()); } // the personId attribute is called person_id so that spring MVC doesn't try to bind it to the personId property of user @ModelAttribute("user") public User formBackingObject(WebRequest request, @RequestParam(required=false, value="person_id") Integer personId) { String userId = request.getParameter("userId"); User u = null; try { u = Context.getUserService().getUser(Integer.valueOf(userId)); } catch (Exception ex) { } if (u == null) { u = new User(); } if (personId != null) { u.setPerson(Context.getPersonService().getPerson(personId)); } else if (u.getPerson() == null) { Person p = new Person(); p.addName(new PersonName()); u.setPerson(p); } return u; } @ModelAttribute("allRoles") public List<Role> getRoles(WebRequest request) { List<Role> roles = Context.getUserService().getAllRoles(); if (roles == null) roles = new Vector<Role>(); for (String s : OpenmrsConstants.AUTO_ROLES()) { Role r = new Role(s); roles.remove(r); } return roles; } @RequestMapping(value="/admin/users/user.form", method=RequestMethod.GET) public String showForm(@RequestParam(required=false, value="userId") Integer userId, @RequestParam(required=false, value="createNewPerson") String createNewPerson, @ModelAttribute("user") User user, ModelMap model) { // the formBackingObject method above sets up user, depending on userId and personId parameters model.addAttribute("isNewUser", isNewUser(user)); if (isNewUser(user) || Context.hasPrivilege(OpenmrsConstants.PRIV_EDIT_USER_PASSWORDS)) model.addAttribute("modifyPasswords", true); if (createNewPerson != null) model.addAttribute("createNewPerson", createNewPerson); if(!isNewUser(user)) model.addAttribute("changePassword",new UserProperties(user.getUserProperties()).isSupposedToChangePassword()); // not using the default view name because I'm converting from an existing form return "admin/users/userForm"; } /** * @should work for an example */ @RequestMapping(value="/admin/users/user.form", method=RequestMethod.POST) public String handleSubmission(WebRequest request, HttpSession httpSession, ModelMap model, @RequestParam(required=false, value="action") String action, @RequestParam(required=false, value="userFormPassword") String password, @RequestParam(required=false, value="secretQuestion") String secretQuestion, @RequestParam(required=false, value="secretAnswer") String secretAnswer, @RequestParam(required=false, value="confirm") String confirm, @RequestParam(required=false, value="forcePassword") Boolean forcePassword, @RequestParam(required=false, value="roleStrings") String[] roles, @RequestParam(required=false, value="createNewPerson") String createNewPerson, @ModelAttribute("user") User user, BindingResult errors) { UserService us = Context.getUserService(); MessageSourceService mss = Context.getMessageSourceService(); if (!Context.isAuthenticated()) { errors.reject("auth.invalid"); } else if (mss.getMessage("User.assumeIdentity").equals(action)) { Context.becomeUser(user.getSystemId()); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "User.assumeIdentity.success"); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ARGS, user.getPersonName()); return "redirect:/index.htm"; } else if (mss.getMessage("User.delete").equals(action)) { try { Context.getUserService().purgeUser(user); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "User.delete.success"); return "redirect:/admin/users/user.list"; } catch (Exception ex) { httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, "User.delete.failure"); log.error("Failed to delete user", ex); return "redirect:/admin/users/user.form?userId="+request.getParameter("userId"); } } else if (mss.getMessage("User.retire").equals(action)) { String retireReason = request.getParameter("retireReason"); if (!(StringUtils.hasText(retireReason))) { errors.rejectValue("retireReason", "User.disableReason.empty"); return showForm(user.getUserId(), createNewPerson, user, model); } else { us.retireUser(user, retireReason); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "User.retiredMessage"); } } else if(mss.getMessage("User.unRetire").equals(action)) { us.unretireUser(user); httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "User.unRetiredMessage"); }else { // check if username is already in the database if (us.hasDuplicateUsername(user)) errors.rejectValue("username", "error.username.taken"); // check if password and password confirm are identical if (password == null || password.equals("XXXXXXXXXXXXXXX")) password = ""; if (confirm == null || confirm.equals("XXXXXXXXXXXXXXX")) confirm = ""; if (!password.equals(confirm)) errors.reject("error.password.match"); if (password.length() == 0 && isNewUser(user)) errors.reject("error.password.weak"); //check password strength if (password.length() > 0) { try { OpenmrsUtil.validatePassword(user.getUsername(), password, user.getSystemId()); } catch (PasswordException e) { errors.reject(e.getMessage()); } } Set<Role> newRoles = new HashSet<Role>(); if (roles != null) { for (String r : roles) { // Make sure that if we already have a detached instance of this role in the // user's roles, that we don't fetch a second copy of that same role from // the database, or else hibernate will throw a NonUniqueObjectException. Role role = null; if (user.getRoles() != null) for (Role test : user.getRoles()) if (test.getRole().equals(r)) role = test; if (role == null) { role = us.getRole(r); user.addRole(role); } newRoles.add(role); } } if (user.getRoles() == null) newRoles.clear(); else user.getRoles().retainAll(newRoles); String[] keys = request.getParameterValues("property"); String[] values = request.getParameterValues("value"); if (keys != null && values != null) { for (int x = 0; x < keys.length; x++) { String key = keys[x]; String val = values[x]; user.setUserProperty(key, val); } } new UserProperties(user.getUserProperties()).setSupposedToChangePassword(forcePassword); UserValidator uv = new UserValidator(); uv.validate(user, errors); if (errors.hasErrors()) { return showForm(user.getUserId(), createNewPerson, user, model); } if (isNewUser(user)){ us.saveUser(user, password); } else { us.saveUser(user, null); if (!password.equals("") && Context.hasPrivilege(OpenmrsConstants.PRIV_EDIT_USER_PASSWORDS)) { if (log.isDebugEnabled()) log.debug("calling changePassword for user " + user + " by user " + Context.getAuthenticatedUser()); us.changePassword(user, password); } } if (StringUtils.hasLength(secretQuestion) && StringUtils.hasLength(secretAnswer)) { us.changeQuestionAnswer(user, secretQuestion, secretAnswer); } httpSession.setAttribute(WebConstants.OPENMRS_MSG_ATTR, "User.saved"); } return "redirect:user.list"; } /** * Superficially determines if this form is being filled out for a new user (basically just * looks for a primary key (user_id) * * @param user * @return true/false if this user is new */ private Boolean isNewUser(User user) { return user == null ? true : user.getUserId() == null; } }