/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package ee.tlu.htk.dippler.managers; import ee.tlu.htk.dippler.entities.User; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.TransactionRequiredException; import javax.persistence.EntityNotFoundException; import javax.persistence.PersistenceContext; import javax.persistence.Query; import java.util.Random; import ee.tlu.htk.dippler.utils.GenerateHash; import ee.tlu.htk.dippler.backoffice.StatusCodes; import ee.tlu.htk.dippler.entities.Client; import ee.tlu.htk.dippler.entities.Organization; import ee.tlu.htk.dippler.utils.permissionChecker; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import org.apache.commons.collections.CollectionUtils; /** * * @author metz */ enum ListActions { LOAD, APPROVE, UNAPPROVE, DELETE, EDIT, CHANGE_ROLE, CHANGE_PASSWORD, CHANGE_EMAIL } @Stateless() public class UserManager implements UserManagerLocal { @PersistenceContext private EntityManager em; private final static String xmlhead = "\n"; public static final Integer LOAD = 1; public static final Integer APPROVE = 95; public static final Integer DELETE = 95; public static final Integer EDIT = 95; public static final Integer CHANGE_PASSWORD = 10; public static final Integer CHANGE_EMAIL = 10; private static Unmarshaller unmarshaller = null; public UserManager() { try { JAXBContext context = JAXBContext.newInstance(User.class); unmarshaller = context.createUnmarshaller(); } catch (JAXBException ex) { Logger.getLogger(UserManager.class.getName()).log(Level.SEVERE, null, ex); } } @Override public String manageUser(String action, String data, User user) { User data_user = unMarshal(data); User manageable_user = null; if (data_user.getId() != null && data_user.getId() > 0) { manageable_user = findById(data_user.getId()); } else if (data_user.getEmail() != null && data_user.getEmail().length() > 0) { manageable_user = findByEmail(data_user.getEmail()); } if (manageable_user != null) { switch (ListActions.valueOf(action)) { case LOAD: if (this.hasPermission(user, LOAD)) { return loadUser(manageable_user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user load"); } case APPROVE: if (this.hasPermission(user, APPROVE)) { return userApprove(data, manageable_user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user approve"); } case UNAPPROVE: if (this.hasPermission(user, APPROVE)) { return userUnApprove(data, manageable_user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user unapprove"); } case DELETE: if (this.hasPermission(user, DELETE)) { return deleteUser(manageable_user, user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user delete"); } case EDIT: if (user.getId() == manageable_user.getId()|| this.hasPermission(user, EDIT)) { return editUser(manageable_user, data_user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user edit"); } case CHANGE_ROLE: if (this.hasPermission(user, APPROVE)) { return changeRole(manageable_user, data_user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for user role change"); } case CHANGE_PASSWORD: if (this.hasPermission(user, CHANGE_PASSWORD)) { return changePassword(manageable_user, data_user, user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for password change."); } case CHANGE_EMAIL: if (this.hasPermission(user, CHANGE_EMAIL)) { return changeEmail(manageable_user, data_user, user); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "No rights for email change."); } default: return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, ""); } } return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, ""); } @Override public void delete(User user) throws IllegalArgumentException, TransactionRequiredException, EntityNotFoundException { em.remove(user); } public String loadUser(User user) { String user_xml = marshal(user); if ( user_xml != null ) { return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", user_xml); } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Not loaded"); } public String editUser(User manageable_user, User data_user) { manageable_user.setFirstname(data_user.getFirstname()); manageable_user.setLastname(data_user.getLastname()); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(data_user)); } public String deleteUser(User manageable_user, User actor) { if (actor.getLevel() >= manageable_user.getLevel()) { if (CollectionUtils.containsAny(actor.getOrganizations(), manageable_user.getOrganizations())) { try { delete(manageable_user); return StatusCodes.respond(StatusCodes.SUCCESS, "User deleted."); } catch (Exception e) { e.printStackTrace(System.err); return StatusCodes.respond(StatusCodes.GENERAL_FAIL, "User delete failed."); } } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Can not delete users from other organization."); } } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Can not delete user with higher level."); } } @Override public User findByEmail(String email) { User user = null; Query find = em.createNamedQuery("User.findByEmail"); find.setParameter("email", email); try { user = (User) find.getSingleResult(); } catch(Exception e ) { //Something went wrong } return user; } /** * Finds user by id, handles null and 0 cases, returns null. * * @param id User identifier * @return User or null */ @Override public User findById(Long id) { if (id != null && id > 0 ) { return em.find(User.class, id); } return null; } @Override public String userAdd(String email, String password, String username, String firstname, String lastname, int level, Client client) { // Generate salt, later on used for password hash compare and generation String salt = generateSalt(); //Let's add new user via EM, not nativeQuery User new_user = new User(); new_user.setEmail(email); new_user.setPassword(generatePasswordHash(password, salt)); new_user.setSalt(salt); new_user.setUsername(username); new_user.setFirstname(firstname); new_user.setLastname(lastname); new_user.setLevel(level); new_user.setApproved(false); Collection orgs = new ArrayList(); orgs.add(client.getOrganization()); new_user.setOrganizations(orgs); em.persist(new_user); int status = StatusCodes.REGISTRATION_ERROR; StringBuilder userData = new StringBuilder(); //If new_user object has ID, then persist worked if ( new_user.getId() != null ) { status = StatusCodes.SUCCESS; userData.append("").append(new_user.getEmail()).append(""); userData.append("").append(new_user.getUsername()).append(""); userData.append("").append(new_user.getFirstname()).append(""); userData.append("").append(new_user.getLastname()).append(""); userData.append("").append(new_user.getLevel()).append(""); } StringBuilder response = new StringBuilder(xmlhead); response.append(""); response.append(status); response.append(""); response.append(userData.toString()); response.append(""); return response.toString(); } public String userApprove(String data, User user) { User u = unMarshal(data); if ( u != null ) { Integer l = 1; if (u.getLevel()>0) { l = u.getLevel(); } user.setApproved(Boolean.TRUE); user.setLevel(l); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(user)); } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Not approved"); } public String userUnApprove(String data, User user) { User u = unMarshal(data); if ( u != null ) { if (u.getLevel()>0) { user.setLevel(u.getLevel()); } user.setApproved(Boolean.FALSE); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(user)); } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Is approved"); } public String changeRole(User manageable_user, User data_user) { if (data_user != null) { if (data_user.getLevel() > 0) { manageable_user.setLevel(data_user.getLevel()); } return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(manageable_user)); } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Could not change role"); } public String changePassword(User manageable_user, User data_user, User actor) { if (data_user != null) { if (!(actor.getLevel() >= manageable_user.getLevel())) { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Can not change password for user with higher level."); } if ( !(permissionChecker.isOwner(manageable_user, actor) || (permissionChecker.isAdmin(actor) && CollectionUtils.containsAny(actor.getOrganizations(), manageable_user.getOrganizations())) )) { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Not allowed to change password for this user."); } if (data_user.getNew_password() != null) { manageable_user.setPassword(generatePasswordHash(data_user.getNew_password(), manageable_user.getSalt())); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(manageable_user)); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Not enough information."); } } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Could not change password."); } public String changeEmail(User manageable_user, User data_user, User actor) { if (data_user != null) { if (!(actor.getLevel() >= manageable_user.getLevel())) { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Can not change email for user with higher level."); } if ( !(permissionChecker.isOwner(manageable_user, actor) || (permissionChecker.isAdmin(actor) && CollectionUtils.containsAny(actor.getOrganizations(), manageable_user.getOrganizations())) )) { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Not allowed to change email for this user."); } if (data_user.getEmail() != null) { manageable_user.setEmail(data_user.getEmail()); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", marshal(manageable_user)); } else { return StatusCodes.respond(StatusCodes.OPERATION_NOT_ALLOWED, "Not enough information."); } } return StatusCodes.respond(StatusCodes.USER_DOES_NOT_EXIST, "Could not change email."); } @Override public User userAuthenticate(String email, String password) { User u = findByEmail(email); if ( u != null ) { // Generate hash from password and salt, check user String passwordhash = generatePasswordHash(password, u.getSalt()); if (u.getEmail().equals(email) && u.getPassword().equals(passwordhash) && u.getApproved()) { return u; } } return null; } @Override public String userXML(User user) { if (user instanceof User) { StringBuilder userData = new StringBuilder(xmlhead); userData.append(""); userData.append("").append(StatusCodes.SUCCESS).append(""); userData.append("").append(user.getId()).append(""); userData.append("").append(user.getEmail()).append(""); userData.append("").append(user.getUsername()).append(""); userData.append("").append(user.getFirstname()).append(""); userData.append("").append(user.getLastname()).append(""); userData.append("").append(user.getLevel()).append(""); userData.append(""); return userData.toString(); } return StatusCodes.SUCCESS.toString(); } @Override public int userCheck(String email) { User u = findByEmail(email); if (u != null && u.getId() > 0) { return StatusCodes.SUCCESS; } return StatusCodes.USER_DOES_NOT_EXIST; } /** * Responds with XML String. Always has success state, even if no matches are found. * * @param term String representing User firstname, lastname, fullname, email or a portion of any of those. * @return A String with response XML. */ @Override public String userSearch(String term) { StringBuilder xml = new StringBuilder(""); try { Query query = em.createNamedQuery("User.searchUsers") .setParameter("term", "%"+term+"%"); List users = query.getResultList(); for(User user : users ){ xml.append(""); xml.append("").append(user.getId().toString()).append(""); xml.append(""); xml.append(""); xml.append(""); } } catch (Exception e) { e.printStackTrace(System.err); } xml.append(""); return StatusCodes.respondWithData(StatusCodes.SUCCESS, "", xml.toString()); } public User unMarshal(String data) { if ( unmarshaller != null ) { try { final User userUNM = (User) unmarshaller.unmarshal(new StringReader(data)); return userUNM; } catch(JAXBException e) { //Could not unmarshal } } return null; } @Override public String marshal(User user) { StringBuilder xml = new StringBuilder(""); xml.append("").append(user.getId()).append(""); xml.append("").append(user.getEmail()).append(""); xml.append("").append(user.getUsername()).append(""); xml.append("").append(user.getFirstname()).append(""); xml.append("").append(user.getLastname()).append(""); xml.append("").append(user.getLevel()).append(""); xml.append(""); return xml.toString(); } @Override public String generateSalt() { Random generator = new Random(); String rand = Long.toString(System.currentTimeMillis() + generator.nextLong()); return GenerateHash.generateMD5(rand).substring(0, 8); } @Override public String generatePasswordHash(String password, String salt) { return GenerateHash.generateSHA1(password + salt); } @Override public boolean hasPermission(User user, int level) { if (user instanceof User && user.getLevel() >= level) { return true; } return false; } }