UserBean.java 7.49 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.enums.Permission;
import fi.insomnia.bortal.enums.RolePermission;
import fi.insomnia.bortal.exceptions.PermissionDeniedException;
import fi.insomnia.bortal.facade.RoleFacade;
import fi.insomnia.bortal.facade.RoleRightFacade;
import fi.insomnia.bortal.facade.UserFacade;
import fi.insomnia.bortal.model.Role;
import fi.insomnia.bortal.model.RoleRight;
import fi.insomnia.bortal.model.User;
import fi.insomnia.bortal.utilities.BortalLocalContextHolder;

/**
 * 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";

    @EJB
    private RoleRightFacade rrfacade;

    /**
     * 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 RoleBeanLocal rolebean;

    @EJB
    private SecurityBeanLocal secubean;

    @EJB
    private EventBeanLocal eventBean;
    @EJB
    private RoleFacade rolefacade;

    /**
     * Default constructor.
     */
    public UserBean() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public User createNewUser(String login, String password) {
        User returnUser = new User();
        returnUser.setLogin(login);
        returnUser.resetPassword(password);
        // Tallennetaan olio kantaan...
        userFacade.create(returnUser);
        em.flush();
        return returnUser;
    }

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

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

    @Override
    public User mergeChanges(User user) {
        fatalPermission(Permission.USER_MANAGEMENT, RolePermission.WRITE);
        return userFacade.merge(user);
    }

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

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

    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.
     */
    public User getAnonUser() {
        User defaultUser = userFacade.findByLogin(DEFAULT_USER_LOGIN);
        if (defaultUser == null) {
            defaultUser = new User();
            defaultUser.setLogin(DEFAULT_USER_LOGIN);
            userFacade.create(defaultUser);
            defaultUser.setSuperadmin(true);
        }
        return defaultUser;
    }

    // TODO: Voisi olla hyvä idea cachettaa... Tätä kutsutaan aika paljon..
    public boolean hasPermission(Permission target, RolePermission permission) {

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

        Boolean ret = BortalLocalContextHolder.hasPermission(target, permission);
        if (ret == null) {
            ret = false;

            Set<Role> checkedRoles = new HashSet<Role>();

            List<Role> rolelist = rolefacade.findForUser(user, eventBean.getCurrentEvent());
            if (getRights(rolelist, target, permission, checkedRoles)) {
                ret = true;
            }
            logger.debug("Perm {} not found from cache. saving to cache: {}", target, ret);
            BortalLocalContextHolder.setPermission(target, permission, ret);
        } else {
            logger.debug("VALUE {} perm {} from cache: {}", new Object[] { target, permission, ret });
        }

        if (logger.isDebugEnabled()) {
            long diffMs = Calendar.getInstance().getTimeInMillis() - start.getTimeInMillis();
            logger.debug("User {} Target {}, permission {} checktime {}ms result: {}", new Object[] { user.getLogin(), target, permission, diffMs, ret });
        }
        // TODO: FIX THIS!! really bad idea....

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

    private boolean getRights(Collection<Role> roles, Permission expectedRight, RolePermission permission, Set<Role> checkedRoles) {

        if (roles == null || roles.isEmpty()) {
            return false;
        }
        for (Role role : roles)
            for (RoleRight rr : role.getRoleRights()) {
                BortalLocalContextHolder.setPermission(rr);
                if (rr.getPermission().equals(expectedRight)) {
                    switch (permission) {
                    case READ:
                        if (rr.isRead()) {
                            return true;
                        }
                        break;
                    case WRITE:
                        if (rr.isWrite()) {
                            return true;
                        }
                        break;
                    case EXECUTE:
                        if (rr.isExecute()) {
                            return true;
                        }
                    }
                }
            }
        checkedRoles.addAll(roles);

        return getRights(rolefacade.findAllParentsExcluding(roles, checkedRoles), expectedRight, permission, checkedRoles);

    }

    @Override
    public boolean hasCurrentUserPermission(Permission permission, RolePermission rolePermission) {
        return this.hasPermission(permission, rolePermission);
    }

    @Override
    public void fatalPermission(Permission target, RolePermission permission, Object... failmessage) {
        boolean ret = hasPermission(target, permission);
        if (!ret) {
            String message = null;
            if (failmessage == null || failmessage.length == 0) {
                message = new StringBuilder("SessionHandler mbean permission exception: Target: ")
                        .append(target.toString())
                        .append(", Permission: ")
                        .append(permission.toString())
                        .toString();
            } else {
                StringBuilder msgbuilder = new StringBuilder();
                for (Object part : failmessage) {
                    msgbuilder.append(part.toString());
                }
                message = msgbuilder.toString();
            }
            throw new PermissionDeniedException(secubean, getCurrentUser(), message);
        }
    }

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

}