package org.nextprot.api.user.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.nextprot.api.commons.exception.NotAuthorizedException; import org.nextprot.api.commons.resource.UserResource; import org.nextprot.api.security.service.impl.NPSecurityContext; import org.nextprot.api.user.dao.UserDao; import org.nextprot.api.user.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.Map; /** * Aspect responsible for checking that services have permission to act on * {@code UserResource} * * Change: 13 January 2015 // Setting it up on security.xml inside the security profile * * * @author fnikitin, dteixeira */ @Aspect public class UserResourceAuthorizationAspect { private static final NotAuthorizedException NOT_AUTHORIZED_EXCEPTION = new NotAuthorizedException("You must be logged in to access this resource"); @Autowired private ApplicationContext context; @Autowired private UserDao userDao; @Around("execution(* org.nextprot.api.user.service.*.*(..)) && !@annotation(org.nextprot.api.commons.resource.AllowedAnonymous)") public Object checkUserAuthorization(ProceedingJoinPoint pjp) throws Throwable { // check that client is logged in SecurityContext sc = SecurityContextHolder.getContext(); if (sc == null || sc.getAuthentication() == null) { throw NOT_AUTHORIZED_EXCEPTION; } // set resource owner with the connected user String currentUser = NPSecurityContext.getCurrentUser(); if (currentUser == null) { throw NOT_AUTHORIZED_EXCEPTION; } checkAdvisedMethodArguments(userDao.getUserByUsername(currentUser), pjp.getArgs()); // proceed to advised method Object o = pjp.proceed(); // void function will not return an object if (o == null) { return null; } else if (o instanceof UserResource) { checkUntrustedUserResource((UserResource) o); } else if (o instanceof Collection) { // check the first resource as all collection's elements are of the same user resource type for (UserResource untrustedUserResource : (Collection<UserResource>)o) { checkUntrustedUserResource(untrustedUserResource); } } else { throw new IllegalStateException("checkUserAuthorization error: unexpected result class "+o.getClass()); } return o; } private void checkAdvisedMethodArguments(User usr, Object[] arguments) { for (Object arg : arguments) { if (arg instanceof UserResource) { UserResource untrustedUserResource = (UserResource) arg; untrustedUserResource.setOwnerName(usr.getUsername()); untrustedUserResource.setOwnerId(usr.getId()); // is the one that own the resource UserResourceAuthorizationChecker delegator = getAuthorizationChecker(untrustedUserResource); if (delegator == null) { throw new IllegalStateException("UserResourceAuthorizationChecker was not found for resource " + untrustedUserResource.getClass()); } delegator.checkAuthorization(untrustedUserResource); NPSecurityContext.checkUserAuthorization(untrustedUserResource); break; // Do it only for the first argument } } } private void checkUntrustedUserResource(UserResource untrustedUserResource) { UserResourceAuthorizationChecker delegator = getAuthorizationChecker(untrustedUserResource); delegator.checkAuthorization(untrustedUserResource); NPSecurityContext.checkUserAuthorization(untrustedUserResource); } private UserResourceAuthorizationChecker getAuthorizationChecker(UserResource userResource) { Map<String, UserResourceAuthorizationChecker> checkers = context.getBeansOfType(UserResourceAuthorizationChecker.class); for (UserResourceAuthorizationChecker checker : checkers.values()) { if (checker.supports(userResource)) { return checker; } } return null; } }