From d5ed14711128bc0ca4774125faee97a4a82a439a Mon Sep 17 00:00:00 2001 From: Arpit Mohan Date: Wed, 19 Feb 2020 12:07:31 +0530 Subject: [PATCH] Getting the AclAspect to work for both Mono & Flux methods. This is done by checking the return type of the function via the joinPoint method signature --- .../appsmith/server/aspects/AclAspect.java | 80 +++++++++++-------- .../server/services/AclPermission.java | 2 - 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspects/AclAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspects/AclAspect.java index 36bb7ed26e..6104e5554c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspects/AclAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspects/AclAspect.java @@ -15,6 +15,7 @@ import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.ReactiveSecurityContextHolder; import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.lang.reflect.Method; @@ -26,46 +27,57 @@ import java.util.Set; @Slf4j public class AclAspect { - @Around("execution(reactor.core.publisher.Mono+ com.appsmith.server.services.CrudService.*(..))") - public Mono checkAuthorization(ProceedingJoinPoint joinPoint) { - try { + @Around("execution(* com.appsmith.server.services.CrudService.*(..))") + public Object checkAuthorization(ProceedingJoinPoint joinPoint) throws Throwable { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + Class returnType = signature.getReturnType(); + + if (Mono.class.isAssignableFrom(returnType)) { return ReactiveSecurityContextHolder.getContext() .map(ctx -> ctx.getAuthentication()) .map(auth -> auth.getPrincipal()) - .filter(principal -> { - User user = (User) principal; - - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - log.debug("Checking the authorization for user: {} for function: {}", user.getEmail(), method.getName()); - - // Get the auth permission to be applied - AclPermission aclPermissionAnnotation = AnnotationUtils.findAnnotation(method, AclPermission.class); - if (aclPermissionAnnotation == null) { - // There are no permission annotations on the method. Continue - return true; - } - String[] authPermission = aclPermissionAnnotation.values(); - - // Get the entity on which permission needs to be applied - String authEntity = joinPoint.getTarget().getClass().getAnnotation(AclEntity.class).value(); - - Set actualPermissions = new HashSet<>(); - if (authPermission != null && authPermission.length > 0) { - for (int i = 0; i < authPermission.length; i++) { - actualPermissions.add(new SimpleGrantedAuthority(authPermission[i] + ":" + authEntity)); - } - } - - log.debug("Permissions required to execute function: {} are: {}", method.getName(), actualPermissions); - return user.getAuthorities().containsAll(actualPermissions); - }) + .filter(principal -> authorizeUser((User) principal, method, joinPoint)) // If the user is not authorized, the filter will not emit. Hence, we return "Unauthorized" .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.UNAUTHORIZED_ACCESS))) // The user is authorized to proceed to function execution - .then((Mono) joinPoint.proceed()); - } catch (Throwable throwable) { - return Mono.error(throwable); + .then((Mono) joinPoint.proceed()); + + } else if (Flux.class.isAssignableFrom(returnType)) { + return ReactiveSecurityContextHolder.getContext() + .map(ctx -> ctx.getAuthentication()) + .map(auth -> auth.getPrincipal()) + .filter(principal -> authorizeUser((User) principal, method, joinPoint)) + // If the user is not authorized, the filter will not emit. Hence, we return "Unauthorized" + .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.UNAUTHORIZED_ACCESS))) + // The user is authorized to proceed to function execution + .thenMany((Flux) joinPoint.proceed()); } + return joinPoint.proceed(); + } + + private boolean authorizeUser(User user, Method method, ProceedingJoinPoint joinPoint) { + log.debug("Checking the authorization for user: {} for function: {}", user.getEmail(), method.getName()); + + // Get the auth permission to be applied + AclPermission aclPermissionAnnotation = AnnotationUtils.findAnnotation(method, AclPermission.class); + if (aclPermissionAnnotation == null) { + // There are no permission annotations on the method. Continue + return true; + } + String[] authPermission = aclPermissionAnnotation.values(); + + // Get the entity on which permission needs to be applied + String authEntity = joinPoint.getTarget().getClass().getAnnotation(AclEntity.class).value(); + + Set actualPermissions = new HashSet<>(); + if (authPermission != null && authPermission.length > 0) { + for (int i = 0; i < authPermission.length; i++) { + actualPermissions.add(new SimpleGrantedAuthority(authPermission[i] + ":" + authEntity)); + } + } + + log.debug("Permissions required to execute function: {} are: {}", method.getName(), actualPermissions); + return user.getAuthorities().containsAll(actualPermissions); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AclPermission.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AclPermission.java index 80b30285f9..45d7b75029 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AclPermission.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/AclPermission.java @@ -1,7 +1,5 @@ package com.appsmith.server.services; -import org.checkerframework.framework.qual.InheritedAnnotation; - import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited;