AclAssignerAspect.java
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed 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.genesys.blocks.security.component;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.blocks.security.model.AclSid;
import org.genesys.blocks.security.service.CustomAclService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* Using aspects to generate default ACL permissions when entities are persisted
* and remove permissions on delete.
*
* @author Maxym Borodenko
* @author Matija Obreza
*/
@Aspect
@Component
@Slf4j
public class AclAssignerAspect {
/** The acl service. */
@Autowired
private CustomAclService aclService;
/**
* Instantiates a new acl assigner aspect.
*/
public AclAssignerAspect() {
log.warn("Enabling {}", getClass().getName());
}
/**
* Ensure owner permissions on persist or update
*
* @param result the result
* @return the object
*/
@AfterReturning(pointcut = "execution(* org.springframework.data.repository.*.save(..)) || execution(* org.springframework.data.repository.*.saveAll(..)) || execution(* org.springframework.data.jpa.repository.*.save(..)) || execution(* org.springframework.data.jpa.repository.*.saveAndFlush(..))", returning = "result")
public Object afterSaveAclObject(final Object result) {
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
if (result instanceof AclAwareModel) {
maybeUpdatePermissions(result);
} else if (result instanceof Iterable) {
// Handle collections of AclAwareModel
final Iterable<?> i = (Iterable<?>) result;
for (final Object o : i) {
maybeUpdatePermissions(o);
}
} else {
log.trace("{} is not instance of AclAwareModel", result);
}
}
return result;
}
/**
* Maybe add creator permissions.
*
* @param obj the obj
*/
private void maybeUpdatePermissions(final Object obj) {
if (obj instanceof AclAwareModel) {
log.trace("Creating or updating permissions for {} ", obj);
aclService.createOrUpdatePermissions((AclAwareModel) obj);
} else {
log.trace("{} is not instance of AclAwareModel", obj);
}
}
/**
* Remove permissions on delete.
*
* @param joinPoint the join point
*/
@Before("execution(* org.springframework.data.repository.*.delete(..)) || execution(* org.springframework.data.repository.*.deleteAll(..)) || execution(* org.springframework.data.jpa.repository.*.deleteInBatch(..))")
public void afterDeleteAclObject(final JoinPoint joinPoint) {
if (joinPoint.getArgs().length == 0) {
return;
}
final Object arg0 = joinPoint.getArgs()[0];
try {
if (arg0 instanceof Long) {
// NOOP
} else if (arg0 instanceof AclSid) {
final AclSid aclSid = (AclSid) arg0;
// Remove permissions owned by SID
aclService.removePermissionsFor(aclSid);
// Remove permissions on SID
maybeRemoveAclAwareModel(aclSid);
} else if (arg0 instanceof AclAwareModel) {
final AclAwareModel aclModel = (AclAwareModel) arg0;
maybeRemoveAclAwareModel(aclModel);
} else if (arg0 instanceof Iterable) {
// Handle collections of AclAwareModel
final Iterable<?> i = (Iterable<?>) arg0;
for (final Object o : i) {
maybeRemoveAclAwareModel(o);
}
} else {
log.trace("{} is not instance of AclAwareModel", arg0);
}
} finally {
// Nothing to do here
}
}
/**
* Maybe remove permissions.
*
* @param obj the obj
*/
private void maybeRemoveAclAwareModel(final Object obj) {
if (obj instanceof AclAwareModel) {
log.debug("Removing ACL entries for model={}", obj);
aclService.removeAclAwareModel((AclAwareModel) obj);
} else {
log.trace("{} is not instance of AclAwareModel", obj);
}
}
}