/*******************************************************************************
* Australian National University Data Commons
* Copyright (C) 2013 The Australian National University
*
* This file is part of Australian National University Data Commons.
*
* Australian National University Data Commons 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.
*
* 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, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package au.edu.anu.datacommons.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import au.edu.anu.datacommons.collectionrequest.Email;
import au.edu.anu.datacommons.data.db.dao.GenericDAO;
import au.edu.anu.datacommons.data.db.dao.GenericDAOImpl;
import au.edu.anu.datacommons.data.db.dao.UserRequestPasswordDAO;
import au.edu.anu.datacommons.data.db.dao.UserRequestPasswordDAOImpl;
import au.edu.anu.datacommons.data.db.dao.UsersDAO;
import au.edu.anu.datacommons.data.db.dao.UsersDAOImpl;
import au.edu.anu.datacommons.data.db.model.Authorities;
import au.edu.anu.datacommons.data.db.model.Groups;
import au.edu.anu.datacommons.data.db.model.PublishLocation;
import au.edu.anu.datacommons.data.db.model.Template;
import au.edu.anu.datacommons.data.db.model.UserRegistered;
import au.edu.anu.datacommons.data.db.model.UserRequestPassword;
import au.edu.anu.datacommons.data.db.model.Users;
import au.edu.anu.datacommons.exception.DataCommonsException;
import au.edu.anu.datacommons.exception.ValidateException;
import au.edu.anu.datacommons.ldap.LdapPerson;
import au.edu.anu.datacommons.ldap.LdapRequest;
import au.edu.anu.datacommons.properties.GlobalProps;
import au.edu.anu.datacommons.publish.service.PublishService;
import au.edu.anu.datacommons.security.CustomUser;
import au.edu.anu.datacommons.security.acl.CustomACLPermission;
import au.edu.anu.datacommons.security.acl.PermissionService;
import au.edu.anu.datacommons.security.service.GroupService;
import au.edu.anu.datacommons.security.service.TemplateService;
import au.edu.anu.datacommons.util.Util;
import com.sun.jersey.api.view.Viewable;
/**
*
* UserResource
*
* Australian National University Data Commons
*
* A set of resources to find and update information about users including their permissions
*
* JUnit Coverage: None
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner (GT) Initial
* 0.2 27/08/2012 Genevieve Turner (GT) Updates for adding
* 0.3 17/09/2012 Genevieve Turner (GT) Fixed issue with updateUserPermissions
* 0.4 14/11/2012 Genevieve Turner (GT) Added a setting of a password for the user if it is null for the getEncodedPassword method
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
*/
@Component
@Scope("request")
@Path("user")
public class UserResource {
static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);
private final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
@Resource(name = "groupServiceImpl")
GroupService groupService;
@Resource(name = "publishServiceImpl")
PublishService publishService;
@Resource(name="templateServiceImpl")
TemplateService templateService;
@Resource(name = "permissionService")
PermissionService permissionService;
@Resource(name = "saltSource")
SaltSource saltSource;
@Resource(name = "mailSender")
JavaMailSenderImpl mailSender;
/**
* getUserInformation
*
* Retrieves the page with the user information
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @return A page with user information
*/
@GET
@Produces(MediaType.TEXT_HTML)
@PreAuthorize("isAuthenticated()")
public Response getUserInformation() {
Map<String, Object> model = new HashMap<String, Object>();
CustomUser customUser = (CustomUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UsersDAO userDAO = new UsersDAOImpl();
Users user = userDAO.getSingleById(customUser.getId());
List<Groups> groups = groupService.getAll();
model.put("groups", groups);
model.put("user", user);
return Response.ok(new Viewable("/user_info.jsp", model)).build();
}
/**
* getPermissionsPage
*
* Retrieves the page for updating user permissions
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* 0.4 14/11/2012 Genevieve Turner (GT) Updated to allow administrative role users able to update permissions
* </pre>
*
* @return A page for updating permissions
*/
@GET
@Path("permissions")
@Produces(MediaType.TEXT_HTML)
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_ANU_USER')")
public Response getPermissionsPage() {
Map<String, Object> model = new HashMap<String, Object>();
List<Groups> groups = groupService.getAllowModifyGroups();
model.put("groups", groups);
List<PublishLocation> publishLocations = publishService.getPublishers();
model.put("publishLocations", publishLocations);
List<Template> templates = templateService.getTemplates();
model.put("templates", templates);
return Response.ok(new Viewable("/user_permissions.jsp", model)).build();
}
/**
* getGroupPermissions
*
* Gets a list of permissions for the user
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @param id
* The id of the group to retrieve permissions for
* @param username
* The name of the user to retireve permissions for
* @return
*/
@GET
@Path("permissions/{id}")
@PreAuthorize("isAuthenticated()")
@Produces(MediaType.APPLICATION_JSON)
public List<Integer> getGroupPermissions(@PathParam("id") Long id, @QueryParam("username") String username) {
List<Permission> permissionList = permissionService.getListOfPermission(Groups.class, id, username);
List<Integer> maskList = new ArrayList<Integer>();
for (Permission permission : permissionList) {
maskList.add(permission.getMask());
}
return maskList;
}
@GET
@Path("permissions/template")
@PreAuthorize("isAuthenticated()")
public List<Long> getTemplatePermissions(@QueryParam("username") String username) {
LOGGER.debug("Request for user {} for template permissions", username);
List<Template> templates = templateService.getTemplatesForUser(username);
List<Long> templateIds = new ArrayList<Long>();
for (Template template : templates) {
templateIds.add(template.getId());
}
return templateIds;
}
@GET
@Path("permissions/publish-location")
public List<Long> getPublishLocationPermissions(@QueryParam("username") String username) {
List<PublishLocation> publishLocations = publishService.getPublishers(username);
List<Long> locationIds = new ArrayList<Long>();
for (PublishLocation location : publishLocations) {
locationIds.add(location.getId());
}
return locationIds;
}
/**
* updateUserPermissions
*
* Updates the users permissions
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* 0.2 17/09/2012 Genevieve Turner (GT) Fixed an issue with the return result not being in the json format
* 0.4 14/11/2012 Genevieve Turner (GT) Updated to allow administrative role users able to update permissions
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param id
* The id of the group to update the permissions for
* @param request
* The http request made
* @return A successful message
*/
@POST
@Path("permissions/{id}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_ANU_USER')")
public String updateUserPermissions(@PathParam("id") Long id, @Context HttpServletRequest request) {
String username = request.getParameter("username");
if (!Util.isNotEmpty(username)) {
throw new ValidateException("No username specified");
}
// Ensure the logged in user has permissions to update this group
List<Groups> groups = groupService.getAllowModifyGroups();
boolean hasGroupPermission = false;
for (int i = 0; !hasGroupPermission && i < groups.size(); i++) {
if (groups.get(i).getId().equals(id)) {
hasGroupPermission = true;
}
}
if (!hasGroupPermission) {
LOGGER.error("{} does not have permissions to update group {}", SecurityContextHolder.getContext()
.getAuthentication().getName(), id);
throw new ValidateException("You do not have permissions to update the group");
}
List<Integer> permissions = new ArrayList<Integer>();
String[] group_permissions = request.getParameterValues("group_perm[]");
if (group_permissions != null) {
for (String mask : group_permissions) {
permissions.add(Integer.valueOf(mask));
}
}
permissionService.saveUserPermissionsForGroup(id, username, permissions);
return "{\"response\": \"Permission Updated\"}";
}
@POST
@Path("permissions")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_ANU_USER')")
public String updateUserPermissions(@FormParam("group_id") Long groupId, @FormParam("group_perm[]") List<Integer> groupPermissions,
@FormParam("publish_location[]") List<Long> publishLocations, @FormParam("template[]") List<Long> templates,
@FormParam("username") String username) {
if (groupId == null && groupPermissions != null && groupPermissions.size() > 0) {
LOGGER.error("No group defined for the permissions");
throw new ValidateException("No group defined for the permissions");
}
if (groupId != null) {
List<Groups> groups = groupService.getAllowModifyGroups();
boolean hasGroupPermission = false;
for (int i = 0; !hasGroupPermission && i < groups.size(); i++) {
if (groups.get(i).getId().equals(groupId)) {
hasGroupPermission = true;
}
}
if (!hasGroupPermission) {
LOGGER.error("{} does not have permissions to update group {}", SecurityContextHolder.getContext()
.getAuthentication().getName(), groupId);
throw new ValidateException("You do not have permissions to update the group");
}
permissionService.saveUserPermissionsForGroup(groupId, username, groupPermissions);
}
Collection<GrantedAuthority> grantedAuthorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
if (grantedAuthorities.contains(new GrantedAuthorityImpl("ROLE_ADMIN"))) {
if (templates != null) {
List<Template> templateObjects = templateService.getTemplatesForUser(username);
List<Long> existingTemplateIds = new ArrayList<Long>();
for (Template template : templateObjects) {
existingTemplateIds.add(template.getId());
}
permissionService.saveUserPermissions(Template.class, templates, existingTemplateIds, username, CustomACLPermission.WRITE);
}
if (publishLocations != null) {
List<PublishLocation> publishLocationObjects = publishService.getPublishers(username);
List<Long> existingLocationIds = new ArrayList<Long>();
for (PublishLocation location: publishLocationObjects) {
existingLocationIds.add(location.getId());
}
permissionService.saveUserPermissions(PublishLocation.class, publishLocations, existingLocationIds, username, CustomACLPermission.PUBLISH);
}
}
return "{\"response\": \"Permissions Updated\"}";
}
/**
* findUser
*
* Find users with the given information
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* 0.4 14/11/2012 Genevieve Turner (GT) Updated to allow administrative role users able to update permissions
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param firstname
* The firstname of the user to find
* @param lastname
* The last of the user to find
* @param uniId
* The university id of the user to find
* @return A list of users with the given criteria
*/
@GET
@Path("find")
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_ANU_USER')")
public List<LdapPerson> findUser(@QueryParam("firstname") String firstname,
@QueryParam("lastname") String lastname, @QueryParam("uniId") String uniId) {
List<Groups> groups = groupService.getAllowModifyGroups();
if (groups.size() == 0) {
LOGGER.error("{} does not have permissions search ldap for other users", SecurityContextHolder.getContext()
.getAuthentication().getName());
throw new DataCommonsException(Status.UNAUTHORIZED, "You do not have permissions to search ldap");
}
LdapRequest ldapRequest = new LdapRequest();
boolean hasInfo = false;
StringBuilder sb = new StringBuilder();
sb.append("(&");
if (Util.isNotEmpty(firstname)) {
sb.append(addLdapVariable(GlobalProps.getProperty(GlobalProps.PROP_LDAPATTR_GIVENNAME), firstname));
hasInfo = true;
}
if (Util.isNotEmpty(lastname)) {
sb.append(addLdapVariable(GlobalProps.getProperty(GlobalProps.PROP_LDAPATTR_FAMILYNAME), lastname));
hasInfo = true;
}
if (Util.isNotEmpty(uniId)) {
sb.append(addLdapVariable(GlobalProps.getProperty(GlobalProps.PROP_LDAPATTR_UNIID), uniId));
hasInfo = true;
}
sb.append(")");
if (!hasInfo) {
throw new ValidateException("A given name, surname or university id is required for the search");
}
ldapRequest.setQuery(sb.toString());
List<LdapPerson> people = null;
try {
people = ldapRequest.search();
LOGGER.trace("Query [fn={}, ln={}, uid={}]. Results: {}", firstname, lastname, uniId, people.size());
} catch (NamingException e) {
LOGGER.error("Error querying ldap", e);
}
return people;
}
/**
* addLdapVariable
*
* Add a ldap variable
*
* <pre>
* Version Date Developer Description
* 0.1 20/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @param variable
* The variable to add
* @param value
* The value to add
* @return The string to add to the ldap search
*/
private String addLdapVariable(String variable, String value) {
StringBuilder sb = new StringBuilder();
sb.append("(");
sb.append(variable);
sb.append("=");
sb.append(value);
sb.append(")");
return sb.toString();
}
/**
* updateUser
*
* Retrieves a page for updating user information
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param request
* Http request information
* @return Response for updating user information
*/
@GET
@Path("update")
@PreAuthorize("hasRole('ROLE_REGISTERED')")
public Response updateUser(@Context HttpServletRequest request) {
Map<String, Object> model = new HashMap<String, Object>();
CustomUser customUser = (CustomUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UsersDAO userDAO = new UsersDAOImpl();
Users user = userDAO.getSingleById(customUser.getId());
if (!user.getUser_type().equals(new Long(2))) {
throw new DataCommonsException(Status.FORBIDDEN, "Only registered users update their information");
}
model.put("user", user);
return Response.ok(new Viewable("/user_update.jsp", model)).build();
}
/**
* saveUpdateUser
*
* Updates user information
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param request
* Http request information
* @param uriInfo
* URI information
* @return The user page
*/
@POST
@Path("update")
@PreAuthorize("hasRole('ROLE_REGISTERED')")
public Response saveUpdateUser(@Context HttpServletRequest request, @Context UriInfo uriInfo) {
String password = request.getParameter("password");
String newpassword = request.getParameter("newpassword");
String newpassword2 = request.getParameter("newpassword2");
Map<String, Object> model = new HashMap<String, Object>();
CustomUser customUser = (CustomUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UsersDAO userDAO = new UsersDAOImpl();
Users user = userDAO.getSingleById(customUser.getId());
if (!user.getUser_type().equals(new Long(2))) {
throw new DataCommonsException(403, "Only registered users update their information");
}
// Verify password
Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
user = setUserDetails(request, user);
if (!user.getPassword().equals(passwordEncoder.encodePassword(password, saltSource.getSalt(customUser)))) {
model.put("error", "Incorrect Password");
model.put("user", user);
throw new WebApplicationException(Response.status(Status.FORBIDDEN)
.entity(new Viewable("/user_update.jsp", model)).build());
}
if (Util.isNotEmpty(newpassword)) {
user.setPassword(getEncodedPassword(newpassword, newpassword2, user));
}
userDAO.update(user);
model.put("user", user);
UriBuilder uriBuilder = UriBuilder.fromUri(uriInfo.getBaseUri()).path("user");
return Response.seeOther(uriBuilder.build()).build();
}
/**
* setUserDetails
*
* Set user details information
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @param request
* Http request information
* @param user
* The user to update user details for
* @return An updated user
*/
private Users setUserDetails(HttpServletRequest request, Users user) {
String firstname = request.getParameter("firstname");
String lastname = request.getParameter("lastname");
String institution = request.getParameter("institution");
String phone = request.getParameter("phone");
String address = request.getParameter("address");
UserRegistered user_registered = user.getUser_registered();
if (user_registered == null) {
user_registered = new UserRegistered();
user_registered.setUser(user);
}
user_registered.setId(user.getId());
user_registered.setGiven_name(firstname);
user_registered.setLast_name(lastname);
user_registered.setInstitution(institution);
user_registered.setPhone(phone);
user_registered.setAddress(address);
user.setUser_registered(user_registered);
return user;
}
public UserRegistered createUserRegistered(HttpServletRequest request, Users user) {
String firstname = request.getParameter("firstname");
String lastname = request.getParameter("lastname");
String institution = request.getParameter("institution");
String phone = request.getParameter("phone");
String address = request.getParameter("address");
UserRegistered userRegistered = new UserRegistered();
userRegistered.setId(user.getId());
userRegistered.setGiven_name(firstname);
userRegistered.setLast_name(lastname);
userRegistered.setInstitution(institution);
userRegistered.setPhone(phone);
userRegistered.setAddress(address);
userRegistered.setUser(user);
return userRegistered;
}
/**
* getNewUser
*
* Gets a new user page
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @return A create new user page
*/
@GET
@Path("new")
public Response getNewUser() {
Viewable viewable = new Viewable("/user_new.jsp");
return Response.ok(viewable).build();
}
/**
* createNewUser
*
* Create a new registered user
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param request
* Http request information
* @return A resposne to the create new user
*/
@POST
@Path("new")
public Response createNewUser(@Context HttpServletRequest request) {
String emailAddr = request.getParameter("email");
String password = request.getParameter("password");
String password2 = request.getParameter("password2");
Users user = new Users();
user.setUsername(emailAddr);
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new GrantedAuthorityImpl("ROLE_REGISTERED"));
String encodedPassword = getEncodedPassword(password, password2, user);
user.setPassword(encodedPassword);
user.setEnabled(Boolean.TRUE);
user.setUser_type(new Long(2));
UsersDAO userDAO = new UsersDAOImpl();
UserRegistered ur = createUserRegistered(request, user);
user.setUser_registered(ur);
user = userDAO.create(user);
Authorities authority = new Authorities();
authority.setUsername(emailAddr);
authority.setAuthority("ROLE_REGISTERED");
GenericDAO<Authorities, String> authorityDAO = new GenericDAOImpl<Authorities, String>(Authorities.class);
authorityDAO.create(authority);
Email email = new Email(mailSender);
email.addRecipient(emailAddr, user.getDisplayName());
email.setSubject("Account Created");
Map<String, String> varMap = new HashMap<String, String>();
varMap.put("displayName", user.getDisplayName());
try {
email.setBody("mailtmpl/newaccount.txt", varMap);
email.send();
} catch (IOException e) {
LOGGER.error("Exception creating email", e);
throw new DataCommonsException(500, "Exception creating email");
}
Map<String, Object> model = new HashMap<String, Object>();
model.put("message", "The user has been created and an email has been sent");
return Response.ok(new Viewable("/message.jsp", model)).build();
}
/**
* getForgotPassword
*
* Gets a forgot password page
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @return Returns a page to notify that the password has been forgotten
*/
@GET
@Path("forgotpassword")
public Response getForgotPassword() {
return Response.ok(new Viewable("/user_forgotpassword.jsp")).build();
}
/**
* sendForgotPasswordEmail
*
* Sends an email about a forgotten password for the specified user
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param request
* Http request information
* @param uriInfo
* URI information
* @return A response to the email request
*/
@POST
@Path("forgotpassword")
public Response sendForgotPasswordEmail(@Context HttpServletRequest request, @Context UriInfo uriInfo) {
String username = request.getParameter("email");
UsersDAO userDAO = new UsersDAOImpl();
Users user = userDAO.getUserByName(username);
Map<String, Object> model = new HashMap<String, Object>();
if (user == null) {
model.put("error", "Email address does not exist in the database");
throw new WebApplicationException(Response.status(400)
.entity(new Viewable("/user_forgotpassword.jsp", model)).build());
}
UserRequestPassword userRequest = new UserRequestPassword();
userRequest.setUser(user);
userRequest.setRequest_date(new Date());
userRequest.setIp_address(request.getRemoteAddr());
userRequest.setLink_id(UUID.randomUUID().toString());
UserRequestPasswordDAO userRequestDAO = new UserRequestPasswordDAOImpl();
userRequestDAO.create(userRequest);
UriBuilder uriBuilder = UriBuilder.fromUri(uriInfo.getBaseUri()).path("user").path("resetpassword")
.queryParam("link", userRequest.getLink_id());
Email email = new Email(mailSender);
email.addRecipient(username, user.getDisplayName());
email.setSubject("Forgotten Password");
Map<String, String> varMap = new HashMap<String, String>();
varMap.put("displayName", user.getDisplayName());
varMap.put("link", uriBuilder.build().toString());
try {
email.setBody("mailtmpl/forgotpassword.txt", varMap);
email.send();
} catch (IOException e) {
LOGGER.error("Exception creating email", e);
throw new DataCommonsException(500, "Exception creating email");
}
return Response.ok(new Viewable("/user_emailsent.jsp")).build();
}
/**
* getResetPassword
*
* Gets a page to reset the password
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* </pre>
*
* @param link
* The link to use to get the password reset page
* @return A page to reset the password
*/
@GET
@Path("resetpassword")
public Response getResetPassword(@QueryParam("link") String link) {
UserRequestPasswordDAO userRequestDAO = new UserRequestPasswordDAOImpl();
UserRequestPassword userRequest = userRequestDAO.getByLink(link);
isValidReset(userRequest);
return Response.ok(new Viewable("/user_forgottenreset.jsp")).build();
}
/**
* resetPassword
*
* Resets the password
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param link
* The link of the password reset request
* @param request
* The http request performed
* @return A response from restting the password
*/
@POST
@Path("resetpassword")
public Response resetPassword(@QueryParam("link") String link, @Context HttpServletRequest request) {
UserRequestPasswordDAO userRequestDAO = new UserRequestPasswordDAOImpl();
UserRequestPassword userRequest = userRequestDAO.getByLink(link);
isValidReset(userRequest);
Users user = userRequest.getUser();
user.setPassword(getEncodedPassword(request.getParameter("password"), request.getParameter("password2"), user));
UsersDAO userDAO = new UsersDAOImpl();
userDAO.update(user);
userRequest.setUsed(Boolean.TRUE);
userRequestDAO.update(userRequest);
Email email = new Email(mailSender);
email.addRecipient(user.getUsername(), user.getDisplayName());
email.setSubject("Forgotten Password");
Map<String, String> varMap = new HashMap<String, String>();
varMap.put("displayName", user.getDisplayName());
try {
email.setBody("mailtmpl/passwordreset.txt", varMap);
email.send();
} catch (IOException e) {
LOGGER.error("Exception creating email", e);
throw new DataCommonsException(500, "Exception creating email for password reset");
}
Map<String, Object> model = new HashMap<String, Object>();
model.put("message", "Password Reset and email has been sent");
return Response.ok(new Viewable("/message.jsp", model)).build();
}
/**
* isValidReset
*
* Verfies that its a valid link for resetting the password. It checks that the link exists in a row and that it has
* not expired.
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param userRequest
* The user request to validate
* @return true if the link is valid
*/
private boolean isValidReset(UserRequestPassword userRequest) {
Date today = new Date();
if (userRequest == null) {
throw new DataCommonsException(404, "Either a the password change request was not found or it is invalid");
} else if (today.getTime() - userRequest.getRequest_date().getTime() - MILLIS_PER_DAY > 0
|| Boolean.TRUE.equals(userRequest.getUsed())) {
throw new DataCommonsException(400, "Password change request has expired");
}
return true;
}
/**
* getEncodedPassword
*
* Verifies that two passwords are the same and returns an md5 salted password
*
* <pre>
* Version Date Developer Description
* 0.2 27/08/2012 Genevieve Turner(GT) Initial
* 0.4 14/11/2012 Genevieve Turner (GT) Added a setting of a password for the user if it is null
* 0.5 02/01/2012 Genevieve Turner (GT) Updated to reflect changes in error handling
* </pre>
*
* @param password
* Password 1 for comparison
* @param password2
* Password 2 for comparison
* @param user
* User to match password for
* @return An md5 salted password
*/
private String getEncodedPassword(String password, String password2, Users user) {
if (password == null || !password.equals(password2)) {
throw new ValidateException("Passwords do not match");
}
Md5PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
// The system appears to have issues if the password is null when retrieving the CustomUser
if (user.getPassword() == null) {
user.setPassword("xxx");
}
CustomUser customUser = new CustomUser(user, true, true, true, true, new ArrayList<GrantedAuthority>());
return passwordEncoder.encodePassword(password, saltSource.getSalt(customUser));
}
@GET
@Path("caslogout")
public Response getCasLogout() {
Response resp = null;
resp = Response.seeOther(UriBuilder.fromUri(GlobalProps.getCasServerUri()).path("logout").build()).build();
return resp;
}
}