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

import java.security.Principal;
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.Resource;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

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

import fi.insomnia.bortal.clientutils.BortalLocalContextHolder;
import fi.insomnia.bortal.enums.Permission;
import fi.insomnia.bortal.enums.RolePermission;
import fi.insomnia.bortal.exceptions.PermissionDeniedException;
import fi.insomnia.bortal.facade.GroupMembershipFacade;
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.Role;
import fi.insomnia.bortal.model.RoleRight;
import fi.insomnia.bortal.model.User;
import fi.insomnia.bortal.model.UserImage;
import fi.insomnia.bortal.util.MailMessage;
import fi.insomnia.bortal.utilities.I18n;

/**
 * Session Bean implementation class UserBean
 */
@LocalBean
@Stateless
public class UserBean implements UserBeanLocal {

    private static final Logger logger = LoggerFactory.getLogger(UserBean.class);
    public static final String DEFAULT_USER_LOGIN = "ANONYMOUS";

    /**
     * Java EE container injektoi tämän luokkamuuttujan luokan luonnin
     * yhteydessä.
     */
    @EJB
    private UserFacade userFacade;
    @PersistenceContext
    private EntityManager em;
    @Resource
    private SessionContext context;

    @EJB
    private SecurityBeanLocal secubean;

    @EJB
    private EventBeanLocal eventBean;

    @EJB
    private UserImageFacade userimagefacade;

    @EJB
    private UtilBeanLocal utilbean;

    @EJB
    private CardTemplateBeanLocal ctbean;
    @EJB
    private PlaceGroupBeanLocal pgbean;
    @EJB
    private AccountEventBeanLocal acbean;
    @EJB
    private GroupMembershipFacade groupMembershipFacade;

    @Override
    public List<User> getUsers() {
        fatalPermission(Permission.USER_MANAGEMENT, RolePermission.READ);

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

    @Override
    public User mergeChanges(User user) {
        if (!isCurrentUser(user)) {
            fatalPermission(Permission.USER_MANAGEMENT, RolePermission.WRITE);
        }

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

        userFacade.evict(ret);
        return ret;
    }

    @Override
    public User getUser(String nick) {
        return userFacade.findByLogin(nick);
    }

    @Override
    public boolean isCurrentUser(User user) {
        return (context.getCallerPrincipal() == null || user == null) ? false : context.getCallerPrincipal().getName().equals(user.getLogin());
    }

    @Override
    public boolean isLoggedIn() {
        return !getAnonUser().equals(getCurrentUser()) || getCurrentUser().isSuperadmin();
    }

    @Override
    public User getCurrentUser() {
        Principal principal = context.getCallerPrincipal();

        User ret = userFacade.findByLogin(principal.getName());
        if (ret == null) {
            ret = getAnonUser();
        }
        return ret;
    }

    /**
     * Makes sure default user and public role exist and the user is member of
     * the role.
     */
    @Override
    public User getAnonUser() {
        User defaultUser = userFacade.findByLogin(DEFAULT_USER_LOGIN);
        if (defaultUser == null) {
            defaultUser = new User();
            defaultUser.setLogin(DEFAULT_USER_LOGIN);
            defaultUser.setNick(DEFAULT_USER_LOGIN);
            userFacade.create(defaultUser);

            defaultUser.setSuperadmin(true);
        }
        return defaultUser;
    }

    @Override
    public boolean hasPermission(Permission target, RolePermission permission) {

        User user = getCurrentUser();
        Calendar start = Calendar.getInstance();

        Boolean ret = BortalLocalContextHolder.hasPermission(target, permission);
        // Boolean ret = BortalLocalContextHolder.hasPermission(target,
        // permission);
        if (ret == null) {
            for (Role role : this.findUsersRoles(user)) {
                if (role == null) {
                    continue;
                }

                for (RoleRight rr : role.getRoleRights()) {
                    BortalLocalContextHolder.setPermission(rr);

                    ret = BortalLocalContextHolder.hasPermission(target, permission);
                    if (ret != null) {
                        break;
                    }

                }
                if (ret != null) {
                    break;
                }
            }
        }

        // TODO: FIX THIS!! really bad idea....

        if (user.isSuperadmin()) {
            return true;
        }

        if (ret == null) {
            ret = false;
            BortalLocalContextHolder.setPermission(target, permission, ret);
        }

        return ret;

    }

    @Override
    public List<Role> findUsersRoles(User u) {
        User currusr = getCurrentUser();
        if (!currusr.equals(u)) {
            fatalNotLoggedIn();
        }

        Set<Role> checkedRoles = new HashSet<Role>();
        addRecursive(checkedRoles, u.getRoles());

        if (isLoggedIn()) {
            LanEvent event = eventBean.getCurrentEvent();

            addRecursive(checkedRoles, event.getDefaultRole());

            addRecursive(checkedRoles, acbean.getRolesFromAccountEvents(u));

            for (GroupMembership member : groupMembershipFacade.findMemberships(event, u)) {
                addRecursive(checkedRoles, member.getPlaceReservation().getProvidesRole());

            }
        }
        return new ArrayList<Role>(checkedRoles);

    }

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

    private 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
    public void fatalPermission(Permission target, RolePermission permission, Object... failmessage) {
        boolean ret = hasPermission(target, permission);
        if (!ret) {
            StringBuilder message = new StringBuilder("Target: ").append(target).append(" permission: ").append(permission);
            if (failmessage == null || failmessage.length == 0) {
                message.append(" MSG: SessionHandler mbean permission exception: Target: ")
                        .append(target)
                        .append(", Permission: ")
                        .append(permission);
            } else {
                for (Object part : failmessage) {
                    message.append(part == null ? "NULL" : part.toString());
                }
            }
            // throw new SecurityException("Foobar");

            throw new PermissionDeniedException(secubean, getCurrentUser(), message.toString());
        }
    }

    @Override
    public void fatalNotLoggedIn() {
        if (!isLoggedIn()) {
            throw new PermissionDeniedException(secubean, getCurrentUser(), "User is not logged in!");
        }
    }

    @Override
    public UserImage uploadImage(Integer userid, String contentType, byte[] image, String filename, String description) {
        fatalNotLoggedIn();
        User user = getCurrentUser();
        logger.debug("uploading image to userid {}", userid);
        if (userid == null || userid.equals(0)) {
            userid = user.getId();
        }

        if (!getCurrentUser().getId().equals(userid)) {
            fatalPermission(Permission.USER_MANAGEMENT, RolePermission.EXECUTE, "usert tried to save picture to userid " + userid + " without sufficient permissions!");
            user = userFacade.find(userid);
        }
        UserImage userimage = new UserImage(user);
        userimage.setMimeType(contentType);
        userimage.setImageData(image);
        userimage.setName(filename);
        userimage.setDescription(description);
        userimagefacade.create(userimage);

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

        userFacade.merge(user);

        return userimage;
    }

    @Override
    public UserImage findUserImage(int id) {

        UserImage ret = null;
        if (id == 0 && isLoggedIn()) {
            ret = getCurrentUser().getCurrentImage();
        } else {
            ret = userimagefacade.find(id);
            if (ret != null && !this.isCurrentUser(ret.getUser())) {
                fatalPermission(Permission.USER_MANAGEMENT, RolePermission.READ, "Not enough rights to access image id: " + id + " for user " + ret.getUser());
            }
        }
        return ret;
    }

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

    @Override
    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(User user, String hash, String mailpath) {
        logger.debug("sending mail! user {} hash {} path {}", new Object[] { user, hash, mailpath });
        if (hash == null || hash.length() < 20 || user == null || user.getEmail() == null || user.getEmail().length() <= 5) {
            return false;
        }
        MailMessage msg = new MailMessage();
        msg.setTo(user);
        msg.setSubject(I18n.get("passwordreset.mailSubject"));
        msg.setMessage(I18n.get("passwordreset.mailBody", mailpath));

        utilbean.sendMail(msg);

        user.setConfirmHash(hash);
        userFacade.merge(user);
        return true;

    }

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

    @Override
    public List<User> getUsers(int page, int pagesize, String sort) {
        return userFacade.findAll(page, pagesize, sort);
    }
}