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
This commit is contained in:
Arpit Mohan 2020-02-19 12:07:31 +05:30
parent bd1c390402
commit d5ed147111
2 changed files with 46 additions and 36 deletions

View File

@ -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<GrantedAuthority> 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<Object>) 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<Object>) 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<GrantedAuthority> 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);
}
}

View File

@ -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;