/**
* Copyright (C) 2012 KRM Associates, Inc. healtheme@krminc.com
*
* Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.krminc.phr.web.form;
import com.krminc.phr.core.AppConfig;
import com.krminc.phr.core.UserConfig;
import com.krminc.phr.dao.PersistenceService;
import com.krminc.phr.domain.*;
import com.sun.jersey.api.core.ResourceContext;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.ws.rs.*;
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.UriInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handles User form.
*
* @author Daniel Shaw (dshaw.com)
*/
public class UserFormProcessor {
final Logger logger = LoggerFactory.getLogger(UserFormProcessor.class);
@Context
protected ResourceContext resourceContext;
@Context
protected UriInfo uriInfo;
public UserFormProcessor() {
}
// @HttpMethod(value="POST")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
// @Consumes(MediaType.MULTIPART_FORM_DATA)
public Response post(
@FormParam("username") String username,
// @FormParam("userimage") java.io.InputStream userImage,
@FormParam("password") String password,
@FormParam("firstname") String firstName,
@FormParam("middlename") String middleName,
@FormParam("lastname") String lastName,
// contact parameters
@FormParam("email") String email,
@FormParam("phonehome") String telnumHome,
@FormParam("phonework") String telnumWork,
@FormParam("phonemobile") String telnumMobile,
@FormParam("fax") String faxnum,
// address parameters
@FormParam("address1") String address1,
@FormParam("address2") String address2,
@FormParam("address3") String address3,
@FormParam("city") String city,
@FormParam("state") String state,
@FormParam("zip") String zip,
// health record parameters
@FormParam("year") int year,
@FormParam("month") int month,
@FormParam("day") int day,
@FormParam("gender") String gender,
// other parameters
@FormParam("by") String createdByUsername,
@FormParam("roles") @DefaultValue(UserConfig.ROLE_PATIENT) List<String> roles,
@FormParam("carenotebook") String careNotebook,
@QueryParam("ajax") String ajax,
@QueryParam("area") String area) {
logger.debug("NEW USER: username {} role {}", username, roles);
logger.debug("CREATED BY: username {}", createdByUsername);
String status = "unknown";
ArrayList<String> errors = new ArrayList<String>();
String responseBaseUri = getResponseBaseUri(area);
boolean ajaxResponse = (ajax != null ? true : false);
logger.debug("USE AJAX RESPONSE: {}", ajaxResponse);
boolean careNotebookVal = (careNotebook != null ? true : false);
// Default user-related object parameters
boolean isPatient = false;
Boolean primary = Boolean.TRUE; // for primary address and health record.
Date dateCreated = new Date();
// Create user object.
// UserId defined when persisted.
User user = new User(username, firstName, middleName, lastName, dateCreated);
//
// if (userImage != null)
// user.setUserImage(userImage);
user.setEmail(email);
user.setTelnumHome(telnumHome);
user.setTelnumWork(telnumWork);
user.setTelnumMobile(telnumMobile);
user.setFaxnum(faxnum);
user.setTotalLogin(0);
// Generate user roles.
// @DefaultValue parameter replacement
if (roles == null || roles.isEmpty()) {
roles = new ArrayList<String>();
roles.add(UserConfig.ROLE_PATIENT);
}
List<UserRole> userRoles = new ArrayList<UserRole>();
for (String role : roles) {
userRoles.add(new UserRole(username, role));
if (role.equalsIgnoreCase(UserConfig.ROLE_PATIENT)) {
isPatient = true;
}
}
//Create primary address record and health record associated with patient.
//UserId assigned after User is generated.
Address address = new Address(primary, address1, address2, address3, city, state, zip, dateCreated);
logger.debug("Address {}", address);
HealthRecord healthRecord = null;
UserPreferences preferences = null;
if (isPatient) {
// User date of birth.
// NOTE: remember Gregorian Calendar MONTH is 0-based, so subtract 1
Calendar dob = null;
if (isPatient) {
try {
dob = new GregorianCalendar(year, month - 1, day);
} catch (Exception e) {
logger.error("ERROR: invalid dob", e);
errors.add("dob");
}
}
healthRecord = new HealthRecord(primary, gender, dob, dateCreated);
preferences = new UserPreferences(createdByUsername);
preferences.setShowCarenotebook(careNotebookVal);
healthRecord.setPreferences(preferences);
}
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
EntityManager em = PersistenceService.getInstance().getEntityManager();
// Server-side username uniqueness check
if (!em.createNamedQuery("User.findByUsername").setParameter("username", username).getResultList().isEmpty()) {
//user with same username already exists
logger.debug("Create User Failed due to duplicate username {}", username);
status = "duplicate";
errors.add(status);
if (ajaxResponse) {
return Response.status(Status.CONFLICT).build();
} else {
return Response.seeOther(uriInfo.getBaseUri()
.resolve(responseBaseUri+"/enroll?status="+status))
.build();
}
}
persistenceSvc.beginTx();
Long id = createUser(user, userRoles, address, preferences, healthRecord, em);
String responsePath = "/users/" + id + "/";
persistenceSvc.commitTx();
status = "success";
if (ajaxResponse) {
return Response.created(uriInfo.getBaseUri()
.resolve(responseBaseUri+responsePath))
.build();
} else {
return Response.seeOther(uriInfo.getBaseUri()
.resolve(responseBaseUri+responsePath+"?status="+status))
.build();
}
} catch (Exception e) {
logger.error("Create User Failed", e);
errors.add("failed");
status = "failed";
if (ajaxResponse) {
return Response.status(Status.BAD_REQUEST).build();
} else {
return Response.seeOther(uriInfo.getBaseUri()
.resolve(responseBaseUri+"/enroll?status="+status))
.build();
}
} finally {
persistenceSvc.close();
}
}
/**
* Persist User, Role, Address and HealthRecord info.
*
* @param user
* @param role
* @param address
* @param healthRecord
* @return userId
*/
protected Long createUser(User user, List<UserRole> roles, Address address, UserPreferences preferences, HealthRecord healthRecord, EntityManager em) {
ArrayList<HealthRecord> hrList = new ArrayList<HealthRecord>();
hrList.add(healthRecord);
user.setHealthRecords(hrList);
user = em.merge(user);
for (UserRole role : roles) {
em.persist(role);
}
//Flush user record to ensure user id is assigned
em.flush();
//Assign user id to address and health record.
Long userId = user.getUserId();
logger.debug("{} User ID set {}", user, userId);
address.setUserId(userId);
em.persist(address);
return userId;
}
/**
* Lookup user by user id.
*
* @param userId
* @return user
*/
private User getUser(Long userId) {
EntityManager em = PersistenceService.getInstance().getEntityManager();
return em.find(User.class, userId);
}
/**
* Ajax submit handler.
*/
/**
* Disable User Account.
*
* @return redirect
*/
@Path("{userId}/disable/")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response disableUserAccount(
@PathParam("userId") Long userId,
@FormParam("active") boolean active,
@FormParam("by") String updatedByUsername,
@QueryParam("area") String area) {
String status = "unknown";
String responseBaseUri = getResponseBaseUri(area);
String redirectUri = responseBaseUri + "/users/" + userId + "/";
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = persistenceSvc.getEntityManager();
User user = em.find(User.class, userId);
user.setActive(active);
em.merge(user);
persistenceSvc.commitTx();
status = "updated&i=" + user.getUserId();
} catch (Exception e) {
logger.error("Disable User Failed", e);
status = "failed";
} finally {
persistenceSvc.close();
}
return Response.seeOther(uriInfo.getBaseUri().resolve(redirectUri + "?status=" + status)).build();
}
/**
* Unlock User Account.
*
* @return redirect
*/
@Path("{userId}/unlock/")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response unlockUserAccount(
@PathParam("userId") Long userId,
@FormParam("by") String updatedByUsername,
@QueryParam("area") String area) {
String status = "unknown";
String responseBaseUri = getResponseBaseUri(area);
String redirectUri = responseBaseUri + "/users/" + userId + "/";
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = persistenceSvc.getEntityManager();
User user = em.find(User.class, userId);
user.setIsLockedOut(false);
//reset security mechanism fields
user.setFailedPasswordAttempts(0);
user.setFailedPasswordWindowStart(null);
em.merge(user);
persistenceSvc.commitTx();
status = "updated&i=" + user.getUserId();
} catch (Exception e) {
logger.error("Unlock User Failed", e);
status = "failed";
} finally {
persistenceSvc.close();
}
return Response.seeOther(uriInfo.getBaseUri().resolve(redirectUri + "?status=" + status)).build();
}
@Path("{userId}/update/")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postPatientUpdate(
@PathParam("userId") Long userId,
/* NOTE: username is not updateable */
@FormParam("password") String password,
@FormParam("firstname") String firstName,
@FormParam("middlename") String middleName,
@FormParam("lastname") String lastName,
// contact parameters
@FormParam("email") String email,
@FormParam("phonehome") String telnumHome,
@FormParam("phonework") String telnumWork,
@FormParam("phonemobile") String telnumMobile,
@FormParam("fax") String faxnum,
// address parameters
@FormParam("address1") String address1,
@FormParam("address2") String address2,
@FormParam("address3") String address3,
@FormParam("city") String city,
@FormParam("state") String state,
@FormParam("zip") String zip,
// health record parameters
@FormParam("year") int year,
@FormParam("month") int month,
@FormParam("day") int day,
@FormParam("gender") String gender,
// other parameters
@FormParam("by") String updatedByUsername,
@FormParam("carenotebook") String careNotebook,
@QueryParam("ajax") String ajax,
@QueryParam("area") String area) {
logger.debug("UPDATED USER: userId {} BY: username {}", userId, updatedByUsername);
String status = "unknown";
ArrayList<String> errors = new ArrayList<String>();
boolean ajaxResponse = (ajax != null ? true : false);
boolean careNotebookVal = (careNotebook != null ? true : false);
logger.debug("AJAX RESPONSE: {}", ajaxResponse);
String redirectUri = getResponseBaseUri(area)+"/users/"+userId+"/";
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = PersistenceService.getInstance().getEntityManager();
User user = getUser(userId);
user.setFirstName(firstName);
user.setMiddleName(middleName);
user.setLastName(lastName);
user.setEmail(email);
user.setTelnumHome(telnumHome);
user.setTelnumWork(telnumWork);
user.setTelnumMobile(telnumMobile);
user.setFaxnum(faxnum);
Address address = user.getPrimaryAddress();
if (address == null || address.getUserId() == null) {
address = new Address(null, userId, Boolean.TRUE, new Date());
}
address.setAddress1(address1);
address.setAddress2(address2);
address.setAddress3(address3);
address.setCity(city);
address.setState(state);
address.setZip(zip);
if (user.isPatient()) {
HealthRecord healthRecord = user.getPrimaryHealthRecord();
healthRecord.setGender(gender);
try {
healthRecord.setDateOfBirth(new GregorianCalendar(year, month - 1, day));
} catch (Exception e) {
logger.error("ERROR: invalid dob");
errors.add("dob");
}
UserPreferences preferences = healthRecord.getPreferences();
if (preferences == null || preferences.getPreferenceId() == null) {
preferences = new UserPreferences(updatedByUsername);
}
preferences.setShowCarenotebook(careNotebookVal);
healthRecord.setPreferences(preferences);
}
em.merge(user);
persistenceSvc.commitTx();
status = "updated";
if (ajaxResponse) {
return Response.status(Status.ACCEPTED).build();
} else {
return Response.seeOther(uriInfo.getBaseUri()
.resolve(redirectUri + "?status=" + status))
.build();
}
} catch (Exception e) {
logger.error("Update User Failed", e);
status = "failed";
if (ajaxResponse) {
return Response.status(Status.BAD_REQUEST).build();
} else {
return Response.seeOther(uriInfo.getBaseUri()
.resolve(redirectUri + "edit?status=" + status))
.build();
}
} finally {
persistenceSvc.close();
}
}
/**
* Reset User Password.
*
* @return redirect
*/
@Path("{userId}/reset/")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response resetUserPassword(
@PathParam("userId") Long userId,
@FormParam("password") String password,
@FormParam("by") String updatedByUsername,
@QueryParam("ajax") String ajax,
@QueryParam("area") String area) {
String status = "unknown";
String redirectUri = getResponseBaseUri(area)+"/users/"+userId+"/";
PersistenceService persistenceSvc = PersistenceService.getInstance();
try {
persistenceSvc.beginTx();
EntityManager em = persistenceSvc.getEntityManager();
User newUser = em.find(User.class, userId);
newUser.setPassword(password);
newUser.setRequiresReset(Boolean.TRUE);
em.merge(newUser);
persistenceSvc.commitTx();
status = "updated";
return Response.seeOther(uriInfo.getBaseUri().resolve(redirectUri + "?status=" + status)).build();
} catch (Exception e) {
logger.error("Password Reset Failed", e);
status = "failed";
return Response.seeOther(uriInfo.getBaseUri().resolve(redirectUri + "reset?status=" + status)).build();
} finally {
persistenceSvc.close();
}
}
/**
* Build response URI.
*/
private String getResponseBaseUri(String area) {
return "."+(area != null && area.equals("admin") ? AppConfig.PATH_ADMIN_ROOT : AppConfig.PATH_USERMANAGER_ROOT);
}
}