org.collectionspace.services.authorization.spring.SpringPermissionManager.java Source code

Java tutorial

Introduction

Here is the source code for org.collectionspace.services.authorization.spring.SpringPermissionManager.java

Source

/**
 *  This document is a part of the source code and related artifacts
 *  for CollectionSpace, an open source collections management system
 *  for museums and related institutions:
    
 *  http://www.collectionspace.org
 *  http://wiki.collectionspace.org
    
 *  Copyright 2009 University of California at Berkeley
    
 *  Licensed under the Educational Community License (ECL), Version 2.0.
 *  You may not use this file except in compliance with this License.
    
 *  You may obtain a copy of the ECL 2.0 License at
    
 *  https://source.collectionspace.org/collection-space/LICENSE.txt
    
 *  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.collectionspace.services.authorization.spring;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.collectionspace.services.authorization.CSpaceAction;
import org.collectionspace.services.authorization.spi.CSpacePermissionManager;
import org.collectionspace.services.authorization.CSpaceResource;
import org.collectionspace.services.authorization.PermissionException;
import org.collectionspace.services.authorization.PermissionNotFoundException;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.AclDataAccessException;
import org.springframework.security.acls.model.AlreadyExistsException;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.transaction.TransactionStatus;

/**
 * Manages permissions in Spring Security
 * @author 
 */
public class SpringPermissionManager implements CSpacePermissionManager {

    final Log log = LogFactory.getLog(SpringPermissionManager.class);
    private SpringAuthorizationProvider provider;

    SpringPermissionManager(SpringAuthorizationProvider provider) {
        this.provider = provider;
    }

    /**
     * addPermissions adds permissions according to the given grant for given
     * resource#action for each given principal
     * @param res
     * @param action
     * @param principals
     * @param grant
     * @throws PermissionException
     */
    @Override
    public void addPermissions(CSpaceResource res, CSpaceAction action, String[] principals, boolean grant)
            throws PermissionException {
        ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
        Sid[] sids = SpringAuthorizationProvider.getSids(principals);
        Permission p = SpringAuthorizationProvider.getPermission(action);
        TransactionStatus status = provider.beginTransaction("addPermssions");

        //add permission for each sid
        for (Sid sid : sids) {
            try {
                addPermission(oid, p, sid, grant);
                if (log.isDebugEnabled()) {
                    log.debug("addpermissions(res,action,prin[], grant), success for " + " res=" + res.toString()
                            + " action=" + action.toString() + " grant=" + grant + " oid=" + oid.toString()
                            + " perm=" + p.toString() + " sid=" + sid.toString());
                }

            } catch (AlreadyExistsException aex) {
                if (log.isWarnEnabled()) {
                    log.warn("addpermissions(res,action,prin[], grant) failed," + " oid=" + oid.toString() + " res="
                            + res.toString() + " grant=" + grant + " action=" + action.toString() + " oid="
                            + oid.toString() + " perm=" + p.toString(), aex);
                }
                //keep going
            } catch (Exception ex) {
                String msg = "addpermissions(res,action,prin[], grant) failed," + " oid=" + oid.toString() + " res="
                        + res.toString() + " action=" + action.toString() + " oid=" + oid.toString() + " perm="
                        + p.toString() + " grant=" + grant;
                if (log.isDebugEnabled()) {
                    log.debug(msg, ex);
                }
                //don't know what might be wrong...stop
                provider.rollbackTransaction(status);
                if (ex instanceof PermissionException) {
                    throw (PermissionException) ex;
                }
                throw new PermissionException(msg, ex);
            }
        } //rof
        provider.commitTransaction(status);
        if (log.isDebugEnabled()) {
            log.debug("addpermissions(res,action,prin[], grant), success for " + " res=" + res.toString()
                    + " action=" + action.toString() + " grant=" + grant + " oid=" + oid.toString() + " perm="
                    + p.toString() + " sids=" + sids.toString());
        }
    }

    /**
     * deletePermissions removes permisions for given resource#action for each given principal
     * @param res
     * @param action
     * @param principals
     * @throws PermissionNotFoundException
     * @throws PermissionException
     */
    @Override
    public void deletePermissions(CSpaceResource res, CSpaceAction action, String[] principals)
            throws PermissionNotFoundException, PermissionException {
        ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
        Sid[] sids = SpringAuthorizationProvider.getSids(principals);
        Permission p = SpringAuthorizationProvider.getPermission(action);
        TransactionStatus status = provider.beginTransaction("deletePermssions");
        //delete permission for each sid
        for (Sid sid : sids) {
            try {
                deletePermissions(oid, p, sid);
                if (log.isDebugEnabled()) {
                    log.debug("deletedpermissions(res,action,prin[]), success for " + " res=" + res.toString()
                            + " action=" + action.toString() + " oid=" + oid.toString() + " perm=" + p.toString()
                            + " sid=" + sid.toString());
                }
            } catch (AclDataAccessException aex) {
                if (log.isWarnEnabled()) {
                    log.debug("deletepermissions(res,action,prin[]) failed, " + " oid=" + oid.toString() + " res="
                            + res.toString() + " action=" + action.toString() + " oid=" + oid.toString() + " perm="
                            + p.toString(), aex);
                }
                //keep going
            } catch (Exception ex) {
                String msg = "deletepermissions(res,action,prin[]) failed," + " oid=" + oid.toString() + " res="
                        + res.toString() + " action=" + action.toString() + " oid=" + oid.toString() + " perm="
                        + p.toString();
                if (log.isDebugEnabled()) {
                    log.debug(msg, ex);
                }
                //don't know what might be wrong...stop
                provider.rollbackTransaction(status);
                if (ex instanceof PermissionException) {
                    throw (PermissionException) ex;
                }
                throw new PermissionException(msg, ex);
            }
        }
        provider.commitTransaction(status);
        if (log.isDebugEnabled()) {
            log.debug("deletedpermissions(res,action,prin[]), success for " + " res=" + res.toString() + " action="
                    + action.toString() + " oid=" + oid.toString() + " perm=" + p.toString() + " sids="
                    + sids.toString());
        }
    }

    /**
     * deletePermissions
     * @param res
     * @param action
     * @throws PermissionNotFoundException
     * @throws PermissionException
     */
    //non-javadoc NOTE: this is a very destructive operation. it would remove all permissions
    //to access given resource#action for ANY role including administrators
    @Override
    public void deletePermissions(CSpaceResource res, CSpaceAction action)
            throws PermissionNotFoundException, PermissionException {
        ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
        Permission p = SpringAuthorizationProvider.getPermission(action);
        TransactionStatus status = provider.beginTransaction("deletePermssions");
        try {
            deletePermissions(oid, p, null);
            provider.commitTransaction(status);
            if (log.isDebugEnabled()) {
                log.debug("deletepermissions(res,action) success, " + " res=" + res.toString() + " action="
                        + action.toString() + " oid=" + oid.toString() + " perm=" + p.toString());
            }
        } catch (AclDataAccessException aex) {
            provider.rollbackTransaction(status);
            log.debug(
                    "deletepermissions(res,action) failed," + " oid=" + oid.toString() + " res=" + res.toString()
                            + " action=" + action.toString() + " oid=" + oid.toString() + " perm=" + p.toString(),
                    aex);
            throw new PermissionException(aex);
        } catch (Exception ex) {
            provider.rollbackTransaction(status);
            String msg = "deletepermissions(res,action,prin[]) failed," + " oid=" + oid.toString() + " res="
                    + res.toString() + " action=" + action.toString() + " oid=" + oid.toString() + " perm="
                    + p.toString();
            if (log.isDebugEnabled()) {
                log.debug(msg, ex);
            }
            if (ex instanceof PermissionException) {
                throw (PermissionException) ex;
            }
            throw new PermissionException(msg, ex);
        }

    }

    /**
     * deletePermissions
     * @param res
     * @throws PermissionNotFoundException
     * @throws PermissionException
     */
    //non-javadoc NOTE: this is a very very destructive operation. it would remove all permissions
    //to access given resource for ANY action for ANY role including administrators
    @Override
    public void deletePermissions(CSpaceResource res) throws PermissionNotFoundException, PermissionException {
        ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
        TransactionStatus status = provider.beginTransaction("deletePermssion");
        try {
            provider.getProviderAclService().deleteAcl(oid, true);
            provider.commitTransaction(status);
            if (log.isDebugEnabled()) {
                log.debug("deletepermissions(res) success, " + " res=" + res.toString() + " oid=" + oid.toString());
            }
        } catch (AclDataAccessException aex) {
            provider.rollbackTransaction(status);
            log.debug("deletepermissions(res) failed," + " oid=" + oid.toString() + " res=" + res.toString()
                    + " oid=" + oid.toString(), aex);
            throw new PermissionException(aex);
        } catch (Exception ex) {
            provider.rollbackTransaction(status);
            String msg = "deletepermissions(res) failed," + " oid=" + oid.toString() + " res=" + res.toString()
                    + " oid=" + oid.toString();
            if (log.isDebugEnabled()) {
                log.debug(msg, ex);
            }
            if (ex instanceof PermissionException) {
                throw (PermissionException) ex;
            }
            throw new PermissionException(msg, ex);
        }
    }

    /**
     * addPermission adds permission grant for given object identity for given permission
     * for given sid
     * @param oid
     * @param permission
     * @param sid
     * @param grant
     * @throws PermissionException
     */
    private void addPermission(ObjectIdentity oid, Permission permission, Sid sid, boolean grant)
            throws PermissionException {
        MutableAcl acl;

        try {
            acl = getAcl(oid);
        } catch (NotFoundException nfe) {
            if (log.isDebugEnabled()) {
                log.debug("addPermission: acl not found for oid=" + oid.toString() + " perm="
                        + permission.toString() + " sid=" + sid.toString() + " grant=" + grant + " adding...");
            }
            acl = provider.getProviderAclService().createAcl(oid);
        }
        acl.insertAce(acl.getEntries().size(), permission, sid, grant);
        provider.getProviderAclService().updateAcl(acl);

        if (log.isDebugEnabled()) {
            log.debug("addPermission: added acl for oid=" + oid.toString() + " perm=" + permission.toString()
                    + " sid=" + sid.toString() + " grant=" + grant);
        }
    }

    /**
     * deletePermissions deletes given permission on given object id for given sid
     * @param oid
     * @param permission
     * @param sid
     */
    //non-javadoc NOTE: if sid is null it would remove ACEs for all sid(s)
    private void deletePermissions(ObjectIdentity oid, Permission permission,
            Sid sid) /** throws AclDataAccessException */
    {
        int i = 0;
        MutableAcl acl = getAcl(oid);
        List<AccessControlEntry> acel = acl.getEntries();
        int aces = acel.size();
        if (log.isDebugEnabled()) {
            log.debug("deletePermissions: for acl oid=" + oid.toString() + " found " + aces + " aces");
        }
        ArrayList<Integer> foundAces = new ArrayList<Integer>();
        Iterator iter = acel.listIterator();
        //not possible to delete while iterating
        while (iter.hasNext()) {
            AccessControlEntry ace = (AccessControlEntry) iter.next();
            if (sid != null) {
                if (ace.getSid().equals(sid) && ace.getPermission().equals(permission)) {
                    foundAces.add(i);
                }
            } else {
                if (ace.getPermission().equals(permission)) {
                    foundAces.add(i);
                }
            }
            i++;
        }
        for (int j = foundAces.size() - 1; j >= 0; j--) {
            //the following operation does not work while iterating in the while loop
            acl.deleteAce(foundAces.get(j)); //autobox
        }
        provider.getProviderAclService().updateAcl(acl);

        if (log.isDebugEnabled()) {
            log.debug("deletePermissions: for acl oid=" + oid.toString() + " deleted " + i + " aces");
        }
    }

    private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
        MutableAcl acl = null;
        acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
        if (log.isDebugEnabled()) {
            log.debug("found acl for oid=" + oid.toString());
        }
        return acl;
    }
}