UserBean.java 11.5 KB
package fi.insomnia.bortal.beans;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.security.DeclareRoles;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.imageio.ImageIO;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.insomnia.bortal.enums.apps.SpecialPermission;
import fi.insomnia.bortal.enums.apps.UserPermission;
import fi.insomnia.bortal.facade.GroupMembershipFacade;
import fi.insomnia.bortal.facade.PlaceGroupFacade;
import fi.insomnia.bortal.facade.RoleFacade;
import fi.insomnia.bortal.facade.UserFacade;
import fi.insomnia.bortal.facade.UserImageFacade;
import fi.insomnia.bortal.model.GroupMembership;
import fi.insomnia.bortal.model.LanEvent;
import fi.insomnia.bortal.model.LanEventPropertyKey;
import fi.insomnia.bortal.model.PlaceGroup;
import fi.insomnia.bortal.model.Role;
import fi.insomnia.bortal.model.User;
import fi.insomnia.bortal.model.UserImage;
import fi.insomnia.bortal.util.MailMessage;
import fi.insomnia.bortal.utilities.I18n;
import fi.insomnia.bortal.utilities.PasswordFunctions;
import fi.insomnia.bortal.utilities.SearchResult;

/**
 * Session Bean implementation class UserBean
 */
@LocalBean
@Stateless
@DeclareRoles({
		UserPermission.S_VIEW_ALL,
		UserPermission.S_CREATE_NEW,
		UserPermission.S_INVITE_USERS,
		UserPermission.S_MODIFY,
		SpecialPermission.S_USER,
})
public class UserBean implements UserBeanLocal {

	private static final Logger logger = LoggerFactory.getLogger(UserBean.class);

	/**
	 * Java EE container injektoi tämän luokkamuuttujan luokan luonnin
	 * yhteydessä.
	 */
	@EJB
	private UserFacade userFacade;

	@PersistenceContext
	private EntityManager em;

	@EJB
	private EventBeanLocal eventBean;

	@EJB
	private UserImageFacade userimagefacade;

	@EJB
	private UtilBeanLocal utilbean;

	@EJB
	private CardTemplateBeanLocal ctbean;
	@EJB
	private AccountEventBeanLocal acbean;

	@EJB
	private PermissionBeanLocal permbean;
	@EJB
	private GroupMembershipFacade gmfacade;

	@EJB
	private UserImageFacade imagefacade;

	@EJB
	private LoggingBeanLocal loggerbean;

	@EJB
	private RoleFacade rolefacade;
	@EJB
	private PlaceGroupFacade pgfacade;

	@Override
	@RolesAllowed(UserPermission.S_VIEW_ALL)
	public List<User> getUsers() {

		List<User> ret = userFacade.findAll();
		return ret;
	}

	@Override
	@RolesAllowed(SpecialPermission.S_USER)
	public User mergeChanges(User user) {
		if (!permbean.isCurrentUser(user) && !permbean.hasPermission(UserPermission.MODIFY)) {
			loggerbean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "User tried to save another user: " + user);
			throw new EJBAccessException("Not enough rights to save user");
		}

		User ret = userFacade.merge(user);
		ctbean.checkPrintedCard(ret);

		return ret;
	}

	@Override
	public List<Role> findUsersRoles(User u) {
		User currusr = permbean.getCurrentUser();
		if (!currusr.equals(u) && !permbean.hasPermission(UserPermission.MODIFY)) {
			loggerbean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "User tried to fetc another users roles: " + u);
			throw new EJBAccessException("Not enough rights to find roles");
		}

		return localFindUsersRoles(u);

	}

	public List<Role> localFindUsersRoles(User u) {
		Set<Role> checkedRoles = new HashSet<Role>();
		if (u != null)
		{
			addRecursive(checkedRoles, rolefacade.findForUser(u));

			if (permbean.isLoggedIn()) {

				LanEvent event = eventBean.getCurrentEvent();
				// add roles from events default role.
				addRecursive(checkedRoles, event.getDefaultRole());

				// add roles from accountEvents of the user
				addRecursive(checkedRoles, acbean.getRolesFromAccountEvents(u));

				for (GroupMembership member : gmfacade.findMemberships(u)) {
					if (member != null && member.getPlaceReservation() != null)
					{
						addRecursive(checkedRoles, member.getPlaceReservation().getProvidesRole());
					}
				}
			}
		}
		return new ArrayList<Role>(checkedRoles);
	}

	private static void addRecursive(Set<Role> checkedRoles, Collection<Role> roles) {
		for (Role r : roles) {
			addRecursive(checkedRoles, r);
		}
	}

	private static void addRecursive(Set<Role> checkedRoles, Role role) {
		if (role == null || checkedRoles.contains(role)) {
			return;
		}
		checkedRoles.add(role);
		for (Role r : role.getParents()) {
			addRecursive(checkedRoles, r);
		}

	}

	@Override
	@RolesAllowed(SpecialPermission.S_USER)
	public UserImage uploadImage(User user, String contentType, byte[] image, String filename, String description) {

		user = userFacade.merge(user);
		logger.debug("uploading image to userid {}", user);

		User curruser = permbean.getCurrentUser();
		if (!curruser.equals(user) && !permbean.hasPermission(UserPermission.MODIFY)) {
			loggerbean.logMessage(SecurityLogType.permissionDenied, curruser, "user tried to save picture to userid " + user + " without sufficient permissions!");
			throw new EJBAccessException("No permission to upload image as another user");
		}

		UserImage userimage = new UserImage(user);
		userimage.setMimeType(contentType);
		userimage.setImageData(image);
		userimage.setName(filename);
		userimage.setDescription(description);

		user.getUserImageList().add(userimage);

		// setting uploaded image as the default.
		user.setCurrentImage(userimage);

		return userimage;
	}

	@Override
	public UserImage findUserimageFORCE(Integer id)
	{
		return userimagefacade.find(id);
	}

	@Override
	public UserImage findUserImage(int id) {

		UserImage ret = null;
		if (id == 0 && permbean.isLoggedIn()) {
			ret = permbean.getCurrentUser().getCurrentImage();
		} else {
			ret = userimagefacade.find(id);
			if (ret != null && !permbean.isCurrentUser(ret.getUser()) && permbean.hasPermission(UserPermission.MODIFY)) {
				loggerbean.logMessage(SecurityLogType.permissionDenied, permbean.getCurrentUser(), "Not enough rights to access image id: " + id + " for user " + ret.getUser());
				throw new EJBAccessException("Not enough permissions to fetch image");
			}

		}
		return ret;
	}

	// @Override
	// public List<User> searchName(String name) {
	// return userFacade.searchForName(name);
	// }

	@Override
	@RolesAllowed(UserPermission.S_CREATE_NEW)
	public User createNewUser(User user, String password) {

		user.resetPassword(password);
		// Tallennetaan olio kantaan...
		userFacade.create(user);
		em.flush();
		return user;
	}

	@Override
	public User findPasswordResetUser(Integer id, String hash) {
		User ret = null;
		if (id != null && hash != null && id > 0 && !hash.isEmpty()) {
			User user = userFacade.find(id);
			if (user != null && hash.equals(user.getConfirmHash())) {
				ret = user;
			}
		}
		return ret;
	}

	@Override
	public boolean resetPassword(User user, String password, String hash) {
		User nuser = userFacade.find(user.getId());
		if (user.equals(nuser) && hash.equals(nuser.getConfirmHash())) {
			logger.debug("Changing user {} password with confirmhash {}", user, hash);
			nuser.setConfirmHash(null);
			nuser.resetPassword(password);
			userFacade.merge(nuser);
			return true;
		}
		return false;
	}

	@Override
	public boolean initPasswordReset(String username, String url) {

		User user = userFacade.findByLogin(username);
		String hash = PasswordFunctions.generateRandomString(25);
		logger.info("Initializing password sending: {}, hash: {}", user, hash);
		String path = MessageFormat.format(url, new Object[] { user.getId(), hash });

		if (hash == null || hash.length() < 20 || user == null || user.getEmail() == null || user.getEmail().length() <= 5) {
			logger.info("Not sending email with params {} {}", new Object[] { user, hash });
			return false;
		}
		MailMessage msg = new MailMessage();
		msg.setTo(user);
		msg.setSubject(I18n.get("passwordreset.mailSubject"));
		msg.setMessage(I18n.get("passwordreset.mailBody", path));

		logger.info("sending mail! user {} hash {} path {}", new Object[] { user, hash, path });
		utilbean.sendMail(msg);
		user.setConfirmHash(hash);
		return true;
	}

	@Override
	@RolesAllowed(UserPermission.S_VIEW_ALL)
	public User findById(Integer id) {
		return userFacade.find(id);
	}

	@Override
	@RolesAllowed(UserPermission.S_VIEW_ALL)
	public SearchResult<User> getUsers(int page, int pagesize, String sort, String search) {
		return userFacade.searchUser(page, pagesize, sort, search);
	}

	// @Override
	// public long getUsersCount(String search) {
	// return userFacade.searchUserCount(search);
	// }

	@Override
	@RolesAllowed(UserPermission.S_INVITE_USERS)
	public boolean invite(String invitemail, String url) {

		List<User> usercheck = userFacade.findByEmail(invitemail.trim());
		if (usercheck.size() > 0) {
			return false;
		}
		User creator = permbean.getCurrentUser();
		LanEvent ev = eventBean.getCurrentEvent();
		PlaceGroup pg = new PlaceGroup(ev, Calendar.getInstance(), Calendar.getInstance(), false);
		pg.setCreator(creator);
		pg.setName("Invitebean");
		String token = PasswordFunctions.generateRandomString(30, PasswordFunctions.ALL_CHARS);
		pg.getMembers().add(new GroupMembership(pg, null, token));
		pgfacade.create(pg);

		MailMessage msg = new MailMessage();
		msg.setSubject(eventBean.getPropertyString(LanEventPropertyKey.INVITEMAIL_SUBJECT));
		msg.setMessage(MessageFormat.format(eventBean.getPropertyString(LanEventPropertyKey.INVITEMAIL_CONTENT), MessageFormat.format(url, token), creator.getWholeName()));
		msg.setToAddress(invitemail);
		utilbean.sendMail(msg);
		return true;
	}

	@Override
	@PermitAll
	public GroupMembership findToken(String token) {
		return gmfacade.findByToken(token);
	}

	@Override
	@PermitAll
	public void createFromToken(User user, String token) {
		GroupMembership gm = findToken(token);
		gm.setUser(user);
		gm.setInviteAccepted(Calendar.getInstance());

		userFacade.create(user);
	}

	@Override
	public UserImage saveCroppedImage(UserImage currimage, int left, int top, int width, int height) throws IOException {
		currimage = imagefacade.find(currimage.getId());
		User user = currimage.getUser();
		logger.info("Current image {}, current user {}", currimage, user);

		user = userFacade.find(user.getId());

		ByteArrayInputStream naamastream = new
				ByteArrayInputStream(currimage.getImageData());
		BufferedImage face;
		face = ImageIO.read(naamastream);
		BufferedImage newFace = face.getSubimage(left, top, width, height);
		ByteArrayOutputStream naamaout = new ByteArrayOutputStream();
		ImageIO.write(newFace, "jpeg", naamaout);

		UserImage ret = new UserImage(user);
		ret.setMimeType(currimage.getMimeType());

		User curruser = permbean.getCurrentUser();

		ret.setDescription("Cropped by: [" + curruser.getId() + "] " + curruser.getWholeName() + " from image: " + currimage.getId());
		ret.setImageData(naamaout.toByteArray());
		ret.setMimeType(currimage.getMimeType());
		if (user.getUserImageList() == null)
		{
			user.setUserImageList(new ArrayList<UserImage>());
		}
		user.getUserImageList().add(ret);
		user.setCurrentImage(ret);

		return ret;

	}

	@Override
	@RolesAllowed(UserPermission.S_CREATE_NEW)
	public void createNewUser(User usr) {
		userFacade.create(usr);

	}

	@Override
	public boolean userExists(String login) {
		User usr = userFacade.findByLogin(login);
		return usr != null;
	}
}