Commit 98209ee3 authored by Matija Obreza's avatar Matija Obreza
Browse files

Deleted ACL

parent 27d1480f
/**
* Copyright 2013 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.crophub.rest.common.acl;
import org.crophub.rest.common.config.ApplicationProps;
import org.crophub.rest.common.model.acl.AclClass;
import org.crophub.rest.common.model.acl.AclEntry;
import org.crophub.rest.common.model.acl.AclObjectIdentity;
import org.crophub.rest.common.model.acl.AclSid;
import org.crophub.rest.common.model.impl.User;
import org.crophub.rest.common.persistence.acl.AclClassPersistence;
import org.crophub.rest.common.persistence.acl.AclEntryPersistence;
import org.crophub.rest.common.persistence.acl.AclObjectIdentityPersistence;
import org.crophub.rest.common.persistence.acl.AclSidPersistence;
import org.crophub.rest.common.security.AuthUserDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Transactional implementation for AclAssigner
*/
@Service
public class AclAssignerService {
private Logger _logger = LoggerFactory.getLogger(getClass());
@Autowired
private AclClassPersistence aclClassPersistence;
@Autowired
private AclEntryPersistence aclEntryPersistence;
@Autowired
private AclObjectIdentityPersistence aclObjectIdentityPersistence;
@Autowired
private AclSidPersistence aclSidPersistence;
@Autowired
private ApplicationProps props;
/**
* ==User model associations==
*/
@Transactional
public void addUserAssociation(User user) {
//assume that auth user has already AclSid implemented
AuthUserDetails authUser = getAuthUser();
//it's ok if it is null
//it can be pre-authorized Admin
AclSid ownerSid = null;
if (authUser != null){
//it also may return null
ownerSid = aclSidPersistence.findBySid(authUser.getUser().getEmail());
}
//create Acl Sid
AclSid aclSid = new AclSid();
aclSid.setPrincipal(true);
aclSid.setSid(user.getEmail());
//save it into db
aclSidPersistence.save(aclSid);
AclClass aclClass = aclClassPersistence.findByAclClass(AclUtil.extractAclClassName(user));
//create object identity
AclObjectIdentity objectIdentity = new AclObjectIdentity();
objectIdentity.setObjectIdIdentity(user.getId());
objectIdentity.setAclClass(aclClass);
objectIdentity.setOwnerSid(ownerSid);
objectIdentity.setEntriesInheriting(false);
//save object identity
aclObjectIdentityPersistence.save(objectIdentity);
//create Acl Entry
AclEntry aclEntry = new AclEntry();
aclEntry.setAclObjectIdentity(objectIdentity);
aclEntry.setAclSid(aclSid);
aclEntry.setAceOrder(1); //TODO check ace order
aclEntry.setGranting(true);
aclEntry.setAuditSuccess(true);
aclEntry.setAuditFailure(true);
//get full access to the own user
aclEntry.setMask(BasePermission.ADMINISTRATION.getMask());
//save ACL
aclEntryPersistence.save(aclEntry);
}
@Transactional
public void removeUserAssociation(User user) {
AclSid aclSid = aclSidPersistence.findBySid(user.getEmail());
if (aclSid != null){
aclSidPersistence.delete(aclSid);
} else {
_logger.warn("Could not find sid for user {}", user.getEmail());
}
}
private AuthUserDetails getAuthUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication == null || !(authentication.getPrincipal() instanceof AuthUserDetails)
? null
: (AuthUserDetails) authentication.getPrincipal();
}
}
/**
* Copyright 2013 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.crophub.rest.common.acl;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.crophub.rest.common.model.AclAwareModel;
import org.crophub.rest.common.model.Permissions;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.model.Permission;
public class AclUtil {
@SuppressWarnings("rawtypes")
private static Map<ClassLoader, Map<Class, String>> CLASSLOADER_CACHE =
new ConcurrentHashMap<ClassLoader, Map<Class, String>>();
public static String extractAclClassName(AclAwareModel o){
return extractAclClassName(o.getClass());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static String extractAclClassName(Class aclAwareModelClass){
Map<Class, String> annotationCache = CLASSLOADER_CACHE.get(aclAwareModelClass.getClassLoader());
if (annotationCache == null){
annotationCache = new ConcurrentHashMap<Class, String>();
CLASSLOADER_CACHE.put(aclAwareModelClass.getClassLoader(), annotationCache);
}
String aclName = annotationCache.get(aclAwareModelClass);
if (aclName == null){
aclName = extractNewAclClassName(aclAwareModelClass);
annotationCache.put(aclAwareModelClass, aclName);
}
return aclName;
}
/**
* Try to get Acl Class name from given object
*
* @param aclAwareModelClass - class name to get Acl Class name
* @return acl class name
*/
private static String extractNewAclClassName(Class<? extends AclAwareModel> aclAwareModelClass){
//try to find out the name from @AclClassDeclaration annotation of class
/*
//todo: check
AclClassDeclaration aclClassDeclaration =
AnnotationUtils.findAnnotation(aclAwareModelClass, AclClassDeclaration.class);
if (aclClassDeclaration != null){
return aclClassDeclaration.value();
}
//try to find out the name from @Entity annotation of class
Entity entityAnnotation = AnnotationUtils.findAnnotation(aclAwareModelClass, Entity.class);
//name should not be empty
if (entityAnnotation != null && StringUtils.isNotEmpty(entityAnnotation.name())){
return entityAnnotation.name();
}
//try to find out the name from @Table annotation of class
Table tableAnnotation = AnnotationUtils.findAnnotation(aclAwareModelClass, Table.class);
//name should not be empty
if (tableAnnotation != null && StringUtils.isNotEmpty(tableAnnotation.name())){
return tableAnnotation.name();
}
//return simple class name otherwise
return aclAwareModelClass.getSimpleName();*/
return aclAwareModelClass.getName();
}
/**
* Obtains ACL permissions from a set of custom permissions
*
* @param permissions - set of custom permissions
* @return - list of permissions
*/
public static Set<Permission> getPermissions(Set<Permissions> permissions) {
Set<Permission> permissionMasks = new HashSet<Permission>();
Iterator<Permissions> iterator = permissions.iterator();
while (iterator.hasNext()) {
Permissions permission = iterator.next();
if (permission == null) {
permission = iterator.next(); //sometimes permission is null
}
//todo: review permission -> acl permission mapping
if (permission.equals(Permissions.READ)) {
permissionMasks.add(BasePermission.READ);
} else if (permission.equals(Permissions.CREATE)) {
permissionMasks.add(BasePermission.CREATE);
} else if (permission.equals(Permissions.UPDATE)) {
permissionMasks.add(BasePermission.WRITE);
} else if (permission.equals(Permissions.DELETE)) {
permissionMasks.add(BasePermission.DELETE);
}
}
return permissionMasks;
}
}
/**
* Copyright 2013 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.crophub.rest.common.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.crophub.rest.common.acl.AclAssignerService;
import org.crophub.rest.common.model.impl.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AclAssignerAspect {
@SuppressWarnings("unused")
private Logger _logger = LoggerFactory.getLogger(getClass());
@Autowired
private AclAssignerService aclAssignerService;
/**
* ==User model associations==
*/
@Around("org.crophub.rest.common.aspect.SystemArchitecture.addUserModel()")
public Object addAssociationsForUser(ProceedingJoinPoint pjp) throws Throwable {
//invoke actual code
Object ret = pjp.proceed();
return ret;
}
@Around("org.crophub.rest.common.aspect.SystemArchitecture.changeUserModel()")
public Object changeAssociationsForUser(ProceedingJoinPoint pjp) throws Throwable {
//invoke actual code
Object ret = pjp.proceed();
return ret;
}
@Around("org.crophub.rest.common.aspect.SystemArchitecture.removeUserModel()")
public Object removeAssociationsForUser(ProceedingJoinPoint pjp) throws Throwable{
//invoke actual code
Object ret = pjp.proceed();
//assume that user to removed has already AclSid implemented
User user = (User) pjp.getArgs()[0];
aclAssignerService.removeUserAssociation(user);
return ret;
}
}
/**
* Copyright 2013 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.crophub.rest.common.listener;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.crophub.rest.common.acl.AclUtil;
import org.crophub.rest.common.model.AclAwareModel;
import org.crophub.rest.common.model.acl.AclClass;
import org.crophub.rest.common.persistence.acl.AclClassPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("aclClassPrefilledListener")
public class AclClassPrefilledListener extends RunAsAdminListener{
@Autowired
private AclClassPersistence aclClassPersistence;
@Autowired(required = false) //for back compatibility
private List<AclAwareModel> aclAwareModels;
@Override
public void init() throws Exception {
if (CollectionUtils.isNotEmpty(aclAwareModels)){
_logger.info("Start pre-filling ACL class names");
for (AclAwareModel aclAwareModel: aclAwareModels){
String aclClassName = AclUtil.extractAclClassName(aclAwareModel);
//if such class name doesn't exist in DB
if (aclClassPersistence.classNamesCount(aclClassName).intValue() == 0){
AclClass aclClass = new AclClass();
aclClass.setAclClass(aclClassName);
//add class into DB
_logger.info("Insert `{}` ACL class", aclClassName);
aclClassPersistence.save(aclClass);
}
}
_logger.info("Pre-filling ACL class names has ended successfully");
}
}
}
/**
* Copyright 2013 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.crophub.rest.common.model;
import java.io.Serializable;
/**
* Interface label for those classes, which is supposed to be
*/
public interface AclAwareModel extends Serializable{
}
/**
* Copyright 2013 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.crophub.rest.common.model;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AclClassDeclaration {
/**
* It should be mandatory, as you would like to use it as concrete class' name
*
* specification of org.crophub.rest.common.model.AclAwareModel entity
*/
String value();
}
/**
* Copyright 2013 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.crophub.rest.common.model.acl;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.crophub.rest.common.model.BusinessModel;
@Entity
@Table(name = "acl_class")
public class AclClass extends BusinessModel{
/**
*
*/
private static final long serialVersionUID = -1923036158097057162L;
@Column(name = "class", nullable = false, unique = true, length = 255)
private String aclClass;
public String getAclClass() {
return aclClass;
}
public void setAclClass(String aclClass) {
this.aclClass = aclClass;
}
}
/**
* Copyright 2013 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.crophub.rest.common.model.acl;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.crophub.rest.common.model.BusinessModel;
@Entity
@Table(name = "acl_entry",
uniqueConstraints = @UniqueConstraint(
columnNames = {"acl_object_identity", "ace_order"}
)
)
public class AclEntry extends BusinessModel{
/**
*
*/
private static final long serialVersionUID = 5024839895363737383L;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "acl_object_identity", nullable = false)
private AclObjectIdentity aclObjectIdentity;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "sid", nullable = false)
private AclSid aclSid;
@Column(name = "ace_order", nullable = false, length = 11)
private long aceOrder;
@Column(name = "mask", nullable = false, length = 11)
private long mask;
@Column(name = "granting", nullable = false, length = 1)
private boolean granting;
@Column(name = "audit_success", nullable = false, length = 1)
private boolean auditSuccess;
@Column(name = "audit_failure", nullable = false, length = 1)
private boolean auditFailure;
public AclObjectIdentity getAclObjectIdentity() {
return aclObjectIdentity;
}