org.ednovo.gooru.security.MethodAuthorizationAspect.java Source code

Java tutorial

Introduction

Here is the source code for org.ednovo.gooru.security.MethodAuthorizationAspect.java

Source

/////////////////////////////////////////////////////////////
// MethodAuthorizationAspect.java
// gooru-api
// Created by Gooru on 2014
// Copyright (c) 2014 Gooru. All rights reserved.
// http://www.goorulearning.org/
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/////////////////////////////////////////////////////////////
package org.ednovo.gooru.security;

import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.ednovo.gooru.core.api.model.GooruAuthenticationToken;
import org.ednovo.gooru.core.api.model.User;
import org.ednovo.gooru.core.constant.GooruOperationConstants;
import org.ednovo.gooru.core.exception.MethodFailureException;
import org.ednovo.gooru.core.security.AuthorizeOperations;
import org.ednovo.gooru.domain.service.user.impl.UserServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Aspect
public class MethodAuthorizationAspect extends OperationAuthorizer {

    private static final Logger LOGGER = LoggerFactory.getLogger(MethodAuthorizationAspect.class);

    @Autowired
    private ParameterNameDiscoverer parameterNameDiscoverer;

    @Autowired
    private UserServiceImpl userService;

    @Around("accessCheckPointcut() && @annotation(authorizeOperations) && @annotation(requestMapping)")
    public Object operationsAuthorization(ProceedingJoinPoint pjp, AuthorizeOperations authorizeOperations,
            RequestMapping requestMapping) throws Throwable {

        // Check method access
        boolean permitted = hasOperationsAuthority(authorizeOperations, pjp);

        // Check party access
        if (authorizeOperations.partyOperations() != null && authorizeOperations.partyOperations().length > 0) {
            permitted = hasPartyAuthorization(authorizeOperations, pjp, requestMapping);
        }

        if (permitted) {
            return pjp.proceed();
        } else {
            throw new AccessDeniedException("Permission Denied");
        }
    }

    @Pointcut("execution(* org.ednovo.gooru.controllers.*.*RestController.*(..)) || "
            + "execution(* org.ednovo.gooru.controllers.*.*.*RestV2Controller.*(..))) ")
    public void accessCheckPointcut() {
    }

    public boolean hasOperationsAuthority(AuthorizeOperations authorizeOperations, ProceedingJoinPoint pjp) {
        if (authorizeOperations.operations().length == 0) {
            return true;
        }

        GooruAuthenticationToken authenticationContext = (GooruAuthenticationToken) SecurityContextHolder
                .getContext().getAuthentication();
        if (authenticationContext != null && authenticationContext.getErrorMessage() != null) {
            if (authenticationContext.getErrorCode() == 403) {
                throw new AccessDeniedException(authenticationContext.getErrorMessage());
            } else {
                throw new MethodFailureException(authenticationContext.getErrorMessage());
            }
        }
        if (authenticationContext == null) {
            throw new AccessDeniedException("Invalid Session Token");
        }
        if (hasAuthorization(authorizeOperations)) {
            return true;
        }
        LOGGER.error("Permission Denied For : " + authenticationContext.getPrincipal() + " To Access : "
                + pjp.getSignature().getName());
        return false;
    }

    public boolean hasPartyAuthorization(AuthorizeOperations authorizeOperations, ProceedingJoinPoint pjp,
            RequestMapping requestMapping) {

        GooruAuthenticationToken authenticationContext = (GooruAuthenticationToken) SecurityContextHolder
                .getContext().getAuthentication();

        if (authenticationContext != null) {
            boolean partyOperationCheck = false;
            String apiCallerPermission = null;
            List<String> partyPermissions = authenticationContext.getUserCredential().getPartyOperations();
            List<String> accessblePermissions = Arrays.asList(authorizeOperations.partyOperations());
            if (partyPermissions != null && accessblePermissions != null) {
                for (String partyPermission : partyPermissions) {
                    if (accessblePermissions.contains(partyPermission)) {
                        partyOperationCheck = true;
                        apiCallerPermission = partyPermission;
                    }
                }
            }
            final Signature signature = pjp.getStaticPart().getSignature();
            if (signature instanceof MethodSignature) {
                final MethodSignature ms = (MethodSignature) signature;
                String[] paramNames = parameterNameDiscoverer.getParameterNames(ms.getMethod());
                Object[] paramValues = pjp.getArgs();
                String partyUidName = authorizeOperations.partyUId();
                String partyUid = "";
                if (paramNames != null && paramValues != null) {
                    for (int paramNameIndex = 0; paramNameIndex < paramNames.length; paramNameIndex++) {
                        String paramName = paramNames[paramNameIndex];
                        if (paramName instanceof String) {
                            if (paramName.equals(partyUidName)) {
                                if (paramValues[paramNameIndex] != null) {
                                    partyUid = (String) paramValues[paramNameIndex];
                                }
                            }
                        }
                    }
                }
                if (!partyUid.isEmpty()) {
                    String[] permittedParties = authenticationContext.getUserCredential().getPartyPermits();
                    List<String> permittedPartiesList = Arrays.asList(permittedParties);
                    String apiCallerOrgUid = authenticationContext.getUserCredential().getOrganizationUid();
                    String userUid = authenticationContext.getUserCredential().getUserUid();
                    User user = userService.findByGooruId(partyUid);
                    User apiCaller = userService.findByGooruId(userUid);
                    RequestMethod[] requestMethods = requestMapping.method();

                    if (partyUid.equals(userUid)) {
                        for (RequestMethod requestMethod : requestMethods) {
                            if (requestMethod.equals(RequestMethod.DELETE)) {
                                return false;
                            }
                        }
                        return true;
                    } else if (user != null && partyOperationCheck && (permittedPartiesList.contains(partyUid)
                            || permittedPartiesList.contains(user.getOrganization().getPartyUid()))) {
                        if (user.getOrganization().getPartyUid().equals(apiCallerOrgUid)) {
                            if (apiCallerPermission.equalsIgnoreCase(GooruOperationConstants.GROUP_ADMIN)
                                    && user.getUserGroup().equals(apiCaller.getUserGroup())) {
                                return true;
                            } else if (apiCallerPermission.equalsIgnoreCase(GooruOperationConstants.ORG_ADMIN)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
}