org.unitime.timetable.security.evaluation.UniTimePermissionCheck.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.security.evaluation.UniTimePermissionCheck.java

Source

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you 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 org.unitime.timetable.security.evaluation;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.unitime.localization.impl.Localization;
import org.unitime.localization.messages.SecurityMessages;
import org.unitime.timetable.defaults.UserProperty;
import org.unitime.timetable.model.Department;
import org.unitime.timetable.model.Session;
import org.unitime.timetable.model.SolverGroup;
import org.unitime.timetable.model.SubjectArea;
import org.unitime.timetable.model.dao._RootDAO;
import org.unitime.timetable.security.Qualifiable;
import org.unitime.timetable.security.UserAuthority;
import org.unitime.timetable.security.UserContext;
import org.unitime.timetable.security.permissions.Permission;
import org.unitime.timetable.security.permissions.Permission.PermissionDepartment;
import org.unitime.timetable.security.permissions.Permission.PermissionSession;
import org.unitime.timetable.security.qualifiers.SimpleQualifier;
import org.unitime.timetable.security.rights.Right;

/**
 * @author Tomas Muller
 */
@Service("unitimePermissionCheck")
public class UniTimePermissionCheck implements PermissionCheck, InitializingBean {
    protected static SecurityMessages MSG = Localization.create(SecurityMessages.class);
    private static Log sLog = LogFactory.getLog(UniTimePermissionCheck.class);

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    PermissionDepartment permissionDepartment;

    @Autowired
    PermissionSession permissionSession;

    @Override
    public void checkPermission(UserContext user, Serializable targetId, String targetType, Right right)
            throws AccessDeniedException {
        if (user == null)
            throw new AccessDeniedException(MSG.noAuthentication(right == null ? "NULL" : right.toString()));

        if (user.getCurrentAuthority() == null)
            throw new AccessDeniedException(MSG.noAuthority(right == null ? "NULL" : right.toString()));

        if (right == null)
            throw new AccessDeniedException(MSG.noRight());

        if (!user.getCurrentAuthority().hasRight(right))
            throw new AccessDeniedException(MSG.missingRight(right.toString()));

        if (targetType == null && right.hasType())
            targetType = right.type().getSimpleName();

        if (targetType == null)
            return;

        if (targetId != null && targetId instanceof Collection) {
            for (Serializable id : (Collection<Serializable>) targetId)
                checkPermission(user, id, targetType, right);
            return;
        }

        if (targetId != null && targetId.getClass().isArray()) {
            for (Serializable id : (Serializable[]) targetId)
                checkPermission(user, id, targetType, right);
            return;
        }

        try {
            String className = targetType;
            if (className.indexOf('.') < 0)
                className = "org.unitime.timetable.model." + className;

            // Special cases

            if (targetId == null && Session.class.getName().equals(className))
                targetId = user.getCurrentAcademicSessionId();

            if (targetId == null && Department.class.getName().equals(className)) {

                AccessDeniedException firstDenial = null;
                for (Department d : Department.getUserDepartments(user)) {
                    try {
                        checkPermission(user, d, right);
                        return;
                    } catch (AccessDeniedException e) {
                        if (firstDenial == null)
                            firstDenial = e;
                    }
                }

                if (firstDenial != null)
                    throw firstDenial;
                throw new AccessDeniedException(MSG.noDepartment(right.toString()));

            }

            if (targetId == null && SubjectArea.class.getName().equals(className)) {

                AccessDeniedException firstDenial = null;
                for (SubjectArea sa : SubjectArea.getUserSubjectAreas(user)) {
                    try {
                        checkPermission(user, sa, right);
                        return;
                    } catch (AccessDeniedException e) {
                        if (firstDenial == null)
                            firstDenial = e;
                    }
                }

                if (firstDenial != null)
                    throw firstDenial;
                throw new AccessDeniedException(MSG.noSubject(right.toString()));
            }

            if (targetId == null && SolverGroup.class.getName().equals(className)) {
                AccessDeniedException firstDenial = null;
                for (SolverGroup g : SolverGroup.getUserSolverGroups(user)) {
                    try {
                        checkPermission(user, g, right);
                        return;
                    } catch (AccessDeniedException e) {
                        if (firstDenial == null)
                            firstDenial = e;
                    }
                }

                if (firstDenial != null)
                    throw firstDenial;
                throw new AccessDeniedException(MSG.noSolverGroup(right.toString()));
            }

            if (targetId == null) {
                throw new AccessDeniedException(MSG.noDomainObject(right.toString(), targetType));
            }

            if (targetId instanceof Qualifiable) {
                Qualifiable q = (Qualifiable) targetId;
                if (targetType == null || targetType.equals(q.getQualifierType())) {
                    checkPermission(user, q.getQualifierId(), q.getQualifierType(), right);
                    return;
                } else {
                    throw new AccessDeniedException(
                            MSG.wrongDomainObject(right.toString(), q.getQualifierType(), targetType));
                }
            }

            if (targetId instanceof String && Department.class.getName().equals(className)) {
                Department dept = Department.findByDeptCode((String) targetId, user.getCurrentAcademicSessionId());
                if (dept != null) {
                    checkPermission(user, dept, right);
                    return;
                }
            }

            if (targetId instanceof String) {
                try {
                    targetId = Long.valueOf((String) targetId);
                } catch (NumberFormatException e) {
                }
            }
            if (!(targetId instanceof Long)) {
                try {
                    targetId = (Serializable) targetId.getClass().getMethod("getUniqueId").invoke(targetId);
                } catch (Exception e) {
                }
                try {
                    targetId = (Serializable) targetId.getClass().getMethod("getId").invoke(targetId);
                } catch (Exception e) {
                }
            }

            Object domainObject = new _RootDAO().getSession().get(Class.forName(className), targetId);
            if (domainObject == null)
                throw new AccessDeniedException(MSG.domainObjectNotExists(right.toString(), targetType));
            checkPermission(user, domainObject, right);
        } catch (AccessDeniedException e) {
            throw e;
        } catch (Exception e) {
            throw new AccessDeniedException(
                    MSG.permissionCheckFailedException(right.toString(), targetType, e.getMessage()));
        }
    }

    @Override
    public void checkPermission(UserContext user, Object domainObject, Right right) throws AccessDeniedException {
        if (user == null)
            throw new AccessDeniedException(MSG.noAuthentication(right == null ? "NULL" : right.toString()));

        if (user.getCurrentAuthority() == null)
            throw new AccessDeniedException(MSG.noAuthority(right == null ? "NULL" : right.toString()));

        if (right == null)
            throw new AccessDeniedException(MSG.noRight());

        if (!user.getCurrentAuthority().hasRight(right))
            throw new AccessDeniedException(MSG.missingRight(right.toString()));

        if (domainObject == null)
            return;

        if (domainObject instanceof Collection) {
            for (Object o : (Collection<?>) domainObject)
                checkPermission(user, o, right);
            return;
        }

        if (domainObject.getClass().isArray()) {
            for (Object o : (Object[]) domainObject)
                checkPermission(user, o, right);
            return;
        }

        if (right.hasType() && !right.type().isInstance(domainObject)) {
            if (domainObject instanceof Qualifiable) {
                checkPermission(user, ((Qualifiable) domainObject).getQualifierId(),
                        ((Qualifiable) domainObject).getQualifierType(), right);
                return;
            }
            if (domainObject instanceof Long) {
                checkPermission(user, (Long) domainObject, right.type().getSimpleName(), right);
                return;
            }
            throw new AccessDeniedException(MSG.wrongDomainObject(right.toString(),
                    domainObject.getClass().getSimpleName(), right.type().getSimpleName()));
        }

        try {
            Permission<?> perm = (Permission<?>) applicationContext.getBean("permission" + right.name(),
                    Permission.class);
            if (perm != null && perm.type().isInstance(domainObject)) {
                if ((Boolean) perm.getClass().getMethod("check", UserContext.class, perm.type()).invoke(perm, user,
                        domainObject)) {
                    return;
                } else {
                    throw new AccessDeniedException(
                            MSG.permissionCheckFailed(right.toString(), domainObject.toString()));
                }
            }
        } catch (BeansException e) {
        } catch (AccessDeniedException e) {
            throw e;
        } catch (Exception e) {
            throw new AccessDeniedException(
                    MSG.permissionCheckFailedException(right.toString(), domainObject.toString(), e.getMessage()));
        }

        if (domainObject instanceof Session) {
            if (permissionSession.check(user, (Session) domainObject)) {
                return;
            } else {
                throw new AccessDeniedException(MSG.sessionCheckFailed(right.toString(), domainObject.toString()));
            }
        }

        if (domainObject instanceof Department) {
            if (permissionDepartment.check(user, (Department) domainObject)) {
                return;
            } else {
                throw new AccessDeniedException(
                        MSG.departmentCheckFailed(right.toString(), domainObject.toString()));
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        for (Right r : Right.values()) {
            try {
                if (r.hasType()) {
                    try {
                        Permission<?> p = (Permission<?>) applicationContext.getBean("permission" + r.name());
                        if (p == null) {
                            sLog.warn("No permission found for " + r + " (" + r.type().getSimpleName() + ").");
                        } else if (!r.type().equals(p.type())) {
                            sLog.warn("Permission " + r + " (" + r.type().getSimpleName() + ") has a wrong type ("
                                    + p.type().getSimpleName() + ").");
                        }
                    } catch (BeansException e) {
                        sLog.warn("Failed to find a permission " + r + " (" + r.type().getSimpleName() + "): "
                                + e.getMessage());
                    }
                }
            } catch (Exception e) {
                sLog.error("Failed to check permission " + r + " (" + r.type().getSimpleName() + "): "
                        + e.getMessage(), e);
            }
        }
    }

    @Override
    public void checkPermissionAnyAuthority(UserContext user, Serializable targetId, String targetType, Right right,
            Qualifiable... filter) throws AccessDeniedException {
        if (user == null)
            throw new AccessDeniedException(MSG.noAuthentication(right == null ? "NULL" : right.toString()));
        AccessDeniedException ret = null;
        authorities: for (UserAuthority authority : user.getAuthorities()) {
            for (Qualifiable q : filter)
                if (!authority.hasQualifier(q))
                    continue authorities;
            try {
                checkPermission(new UserContextWrapper(user, authority), targetId, targetType, right);
                return;
            } catch (AccessDeniedException e) {
                if (ret == null)
                    ret = e;
            }
        }
        throw (ret != null ? ret : new AccessDeniedException(MSG.noMatchingAuthority(right.toString())));
    }

    @Override
    public void checkPermissionAnyAuthority(UserContext user, Object targetObject, Right right,
            Qualifiable... filter) throws AccessDeniedException {
        if (user == null)
            throw new AccessDeniedException(MSG.noAuthentication(right == null ? "NULL" : right.toString()));
        AccessDeniedException ret = null;
        authorities: for (UserAuthority authority : user.getAuthorities()) {
            for (Qualifiable q : filter)
                if (!authority.hasQualifier(q))
                    continue authorities;
            try {
                checkPermission(new UserContextWrapper(user, authority), targetObject, right);
                return;
            } catch (AccessDeniedException e) {
                if (ret == null)
                    ret = e;
            }
        }
        throw (ret != null ? ret : new AccessDeniedException(MSG.noMatchingAuthority(right.toString())));
    }

    @Override
    public boolean hasPermission(UserContext user, Serializable targetId, String targetType, Right right) {
        if (user == null || user.getCurrentAuthority() == null)
            return false;
        if (right == null || !user.getCurrentAuthority().hasRight(right))
            return false;

        if (targetType == null && right.hasType())
            targetType = right.type().getSimpleName();

        if (targetType == null)
            return true;

        if (targetId != null && targetId instanceof Collection) {
            for (Serializable id : (Collection<Serializable>) targetId)
                if (!hasPermission(user, id, targetType, right))
                    return false;
            return true;
        }

        if (targetId != null && targetId.getClass().isArray()) {
            for (Serializable id : (Serializable[]) targetId)
                if (!hasPermission(user, id, targetType, right))
                    return false;
            return true;
        }

        try {
            String className = targetType;
            if (className.indexOf('.') < 0)
                className = "org.unitime.timetable.model." + className;

            // Special cases

            if (targetId == null && Session.class.getName().equals(className))
                targetId = user.getCurrentAcademicSessionId();

            if (targetId == null && Department.class.getName().equals(className)) {

                for (Department d : Department.getUserDepartments(user))
                    if (hasPermission(user, d, right))
                        return true;

                return false;
            }

            if (targetId == null && SubjectArea.class.getName().equals(className)) {

                for (SubjectArea sa : SubjectArea.getUserSubjectAreas(user))
                    if (hasPermission(user, sa, right))
                        return true;

                return false;
            }

            if (targetId == null && SolverGroup.class.getName().equals(className)) {
                for (SolverGroup g : SolverGroup.getUserSolverGroups(user))
                    if (hasPermission(user, g, right))
                        return true;

                return false;
            }

            if (targetId == null)
                return false;

            if (targetId instanceof Qualifiable) {
                Qualifiable q = (Qualifiable) targetId;
                if (targetType == null || targetType.equals(q.getQualifierType()))
                    return hasPermission(user, q.getQualifierId(), q.getQualifierType(), right);
                else
                    return false;
            }

            if (targetId instanceof String && Department.class.getName().equals(className)) {
                Department dept = Department.findByDeptCode((String) targetId, user.getCurrentAcademicSessionId());
                if (dept != null)
                    return hasPermission(user, dept, right);
            }

            if (targetId instanceof String) {
                try {
                    targetId = Long.valueOf((String) targetId);
                } catch (NumberFormatException e) {
                }
            }
            if (!(targetId instanceof Long)) {
                try {
                    targetId = (Serializable) targetId.getClass().getMethod("getUniqueId").invoke(targetId);
                } catch (Exception e) {
                }
                try {
                    targetId = (Serializable) targetId.getClass().getMethod("getId").invoke(targetId);
                } catch (Exception e) {
                }
            }

            Object domainObject = new _RootDAO().getSession().get(Class.forName(className), targetId);
            if (domainObject == null)
                return false;

            return hasPermission(user, domainObject, right);
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public boolean hasPermission(UserContext user, Object domainObject, Right right) {
        if (user == null || user.getCurrentAuthority() == null)
            return false;
        if (right == null || !user.getCurrentAuthority().hasRight(right))
            return false;

        if (domainObject == null)
            return true;

        if (domainObject instanceof Collection) {
            for (Object o : (Collection<?>) domainObject)
                if (!hasPermission(user, o, right))
                    return false;
            return true;
        }

        if (domainObject.getClass().isArray()) {
            for (Object o : (Object[]) domainObject)
                if (!hasPermission(user, o, right))
                    return false;
            return true;
        }

        if (right.hasType() && !right.type().isInstance(domainObject)) {
            if (domainObject instanceof Qualifiable) {
                return hasPermission(user, ((Qualifiable) domainObject).getQualifierId(),
                        ((Qualifiable) domainObject).getQualifierType(), right);
            }
            if (domainObject instanceof Long) {
                return hasPermission(user, (Long) domainObject, right.type().getSimpleName(), right);
            }
            return false;
        }

        try {
            Permission<?> perm = (Permission<?>) applicationContext.getBean("permission" + right.name(),
                    Permission.class);
            if (perm != null && perm.type().isInstance(domainObject))
                return (Boolean) perm.getClass().getMethod("check", UserContext.class, perm.type()).invoke(perm,
                        user, domainObject);
        } catch (Exception e) {
            return false;
        }

        if (domainObject instanceof Session)
            return permissionSession.check(user, (Session) domainObject);

        if (domainObject instanceof Department)
            return permissionDepartment.check(user, (Department) domainObject);

        return true;
    }

    @Override
    public boolean hasPermissionAnyAuthority(UserContext user, Serializable targetId, String targetType,
            Right right, Qualifiable... filter) {
        if (user == null)
            return false;
        authorities: for (UserAuthority authority : user.getAuthorities()) {
            for (Qualifiable q : filter)
                if (!authority.hasQualifier(q))
                    continue authorities;
            if (hasPermission(new UserContextWrapper(user, authority), targetId, targetType, right))
                return true;
        }
        return false;
    }

    @Override
    public boolean hasPermissionAnyAuthority(UserContext user, Object targetObject, Right right,
            Qualifiable... filter) throws AccessDeniedException {
        if (user == null)
            return false;
        authorities: for (UserAuthority authority : user.getAuthorities()) {
            for (Qualifiable q : filter)
                if (!authority.hasQualifier(q))
                    continue authorities;
            if (hasPermission(new UserContextWrapper(user, authority), targetObject, right))
                return true;
        }
        return false;
    }

    public static class UserContextWrapper implements UserContext {
        private static final long serialVersionUID = 1L;
        UserAuthority iAuthority;
        UserContext iContext;

        public UserContextWrapper(UserContext context, UserAuthority authority) {
            iContext = context;
            iAuthority = authority;
        }

        @Override
        public boolean isEnabled() {
            return iContext.isEnabled();
        }

        @Override
        public boolean isCredentialsNonExpired() {
            return iContext.isCredentialsNonExpired();
        }

        @Override
        public boolean isAccountNonLocked() {
            return iContext.isAccountNonLocked();
        }

        @Override
        public boolean isAccountNonExpired() {
            return iContext.isAccountNonExpired();
        }

        @Override
        public String getUsername() {
            return iContext.getUsername();
        }

        @Override
        public String getPassword() {
            return iContext.getPassword();
        }

        @Override
        public void setProperty(UserProperty property, String value) {
            iContext.setProperty(property, value);
        }

        @Override
        public void setProperty(String key, String value) {
            iContext.setProperty(key, value);
        }

        @Override
        public void setCurrentAuthority(UserAuthority authority) {
            iAuthority = authority;
        }

        @Override
        public boolean hasRole(String role) {
            return iContext.hasRole(role);
        }

        @Override
        public boolean hasDepartment(Long departmentId) {
            return iAuthority.hasQualifier(new SimpleQualifier(Department.class.getSimpleName(), departmentId));
        }

        @Override
        public boolean hasAuthority(String authority) {
            return iContext.hasAuthority(authority);
        }

        @Override
        public boolean hasAuthority(String role, Long uniqueId) {
            return iContext.hasAuthority(role, uniqueId);
        }

        @Override
        public boolean hasAuthority(UserAuthority authority) {
            return iContext.hasAuthority(authority);
        }

        @Override
        public String getProperty(UserProperty property) {
            return iContext.getProperty(property);
        }

        @Override
        public String getProperty(String key, String defaultValue) {
            return iContext.getProperty(key, defaultValue);
        }

        @Override
        public String getProperty(String key) {
            return iContext.getProperty(key);
        }

        @Override
        public Map<String, String> getProperties() {
            return iContext.getProperties();
        }

        @Override
        public String getName() {
            return iContext.getName();
        }

        @Override
        public String getExternalUserId() {
            return iContext.getExternalUserId();
        }

        @Override
        public String getEmail() {
            return iContext.getEmail();
        }

        @Override
        public UserAuthority getCurrentAuthority() {
            return iAuthority;
        }

        @Override
        public Long getCurrentAcademicSessionId() {
            return (Long) (iAuthority.getAcademicSession() == null ? null
                    : iAuthority.getAcademicSession().getQualifierId());
        }

        @Override
        public UserAuthority getAuthority(String authority) {
            return iContext.getAuthority(authority);
        }

        @Override
        public UserAuthority getAuthority(String role, Long uniqueId) {
            return iContext.getAuthority(role, uniqueId);
        }

        @Override
        public List<? extends UserAuthority> getAuthorities(String role, Qualifiable... filter) {
            return iContext.getAuthorities(role, filter);
        }

        @Override
        public Collection<? extends UserAuthority> getAuthorities() {
            return iContext.getAuthorities();
        }

        @Override
        public String getTrueExternalUserId() {
            return iContext.getTrueExternalUserId();
        }

        @Override
        public String getTrueName() {
            return iContext.getTrueName();
        }
    }
}