Package org.exist.xmldb

Source Code of org.exist.xmldb.LocalUserManagementService

package org.exist.xmldb;

import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.exist.EXistException;
import org.exist.collections.triggers.TriggerException;
import org.exist.dom.DocumentImpl;
import org.exist.security.ACLPermission;
import org.exist.security.Group;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.security.Subject;
import org.exist.security.Account;
import org.exist.security.User;
import org.exist.security.SecurityManager;
import org.exist.security.internal.aider.ACEAider;
import org.exist.security.internal.aider.UserAider;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.lock.Lock;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.LockException;
import org.exist.util.SyntaxException;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.Resource;
import org.xmldb.api.base.XMLDBException;

/**
* Local Implementation (i.e. embedded) of an eXist-specific service
* which provides methods to manage users and
* permissions.
*
* @author Wolfgang Meier <meier@ifs.tu-darmstadt.de>
* @author Modified by {Marco.Tampucci, Massimo.Martinelli} @isti.cnr.it
* @author Adam Retter <adam@exist-db.org>
*/
public class LocalUserManagementService implements EXistUserManagementService {
   
    private LocalCollection collection;

    private final BrokerPool pool;
    private final Subject user;

    public LocalUserManagementService(Subject user, BrokerPool pool, LocalCollection collection) {
        this.pool = pool;
        this.collection = collection;
        this.user = user;
    }
   
    @Override
    public String getName() {
        return "UserManagementService";
    }
   
    @Override
    public String getVersion() {
        return "1.0";
    }

    @Override
    public void addAccount(final Account u) throws XMLDBException {
   
        final SecurityManager manager = pool.getSecurityManager();
       
        if(!manager.hasAdminPrivileges(user)) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, " you are not allowed to change this user");
        }
       
        if(manager.hasAccount(u.getName())) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "user " + u.getName() + " exists");
        }
       
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException {
                    manager.addAccount(u);
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e);
        }
    }

    @Override
    public void addGroup(final Group group) throws XMLDBException {
        final SecurityManager manager = pool.getSecurityManager();
   
        if(!manager.hasAdminPrivileges(user)) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, " you are not allowed to add role");
        }

        if(manager.hasGroup(group.getName())) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "group '" + group.getName() + "' exists");
        }
   
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException {
                    manager.addGroup(group);
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e);
        }
    }

    @Override
    public void setUserPrimaryGroup(final String username, final String groupName) throws XMLDBException {
        final SecurityManager manager = pool.getSecurityManager();
   
        if(!manager.hasGroup(groupName)) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Group '" + groupName + "' does not exist!");
        }
       
        if(!manager.hasAdminPrivileges(user)) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Not allowed to modify user");
        }
   
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException {
                    final Account account = manager.getAccount(username);
                    final Group group = manager.getGroup(groupName);
                    account.setPrimaryGroup(group);
                    manager.updateAccount(account);
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e);
        }
    }
   
    @Override
    public void setPermissions(final Resource resource, final Permission perm) throws XMLDBException {
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            document.setPermissions(perm);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }
    }

    @Override
    public void setPermissions(final Collection child, final Permission perm) throws XMLDBException {
 
        final XmldbURI childUri = XmldbURI.create(child.getName());
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, childUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, LockException {
                            collection.setPermissions(perm);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + childUri.toString() + "'", e);
        }
    }
   
    @Override
    public void setPermissions(Collection child, final String owner, final String group, final int mode, final List<ACEAider> aces) throws XMLDBException {
           
        final XmldbURI childUri = XmldbURI.create(child.getName());
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, childUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, LockException {
                            final Permission permission = collection.getPermissionsNoLock();
                            permission.setOwner(owner);
                            permission.setGroup(group);
                            permission.setMode(mode);
                            if(permission instanceof ACLPermission) {
                                final ACLPermission aclPermission = (ACLPermission)permission;
                                aclPermission.clear();
                                for(final ACEAider ace : aces) {
                                    aclPermission.addACE(ace.getAccessType(), ace.getTarget(), ace.getWho(), ace.getMode());
                                }
                            }
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + childUri.toString() + "'", e);
        }
    }
       
    @Override
    public void setPermissions(final Resource resource, final String owner, final String group, final int mode, final List<ACEAider> aces) throws XMLDBException {
           
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            final Permission permission = document.getPermissions();
                            permission.setOwner(owner);
                            permission.setGroup(group);
                            permission.setMode(mode);
                            if(permission instanceof ACLPermission) {
                                final ACLPermission aclPermission = (ACLPermission)permission;
                                aclPermission.clear();
                                for(final ACEAider ace : aces) {
                                    aclPermission.addACE(ace.getAccessType(), ace.getTarget(), ace.getWho(), ace.getMode());
                                }
                            }
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }
    }


    @Override
    public void chmod(final String modeStr) throws XMLDBException {
       
        final XmldbURI collUri = collection.getPathURI();
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                   return modifyCollection(broker, collUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, SyntaxException, LockException {
                            collection.setPermissions(modeStr);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + collUri.toString() + "'", e);
        }
    }

    @Override
    public void chmod(final Resource resource, final int mode) throws XMLDBException {
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            document.getPermissions().setMode(mode);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }
    }

    @Override
    public void chmod(final int mode) throws XMLDBException {
        final XmldbURI collUri = collection.getPathURI();
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, collUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, SyntaxException, LockException {
                            collection.setPermissions(mode);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + collUri.toString() + "'", e);
        }
    }

    @Override
    public void chmod(final Resource resource, final String modeStr) throws XMLDBException {
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws SyntaxException, PermissionDeniedException, LockException {
                            document.getPermissions().setMode(modeStr);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }
    }

    @Override
    public void chgrp(final String group) throws XMLDBException {
        final XmldbURI collUri = collection.getPathURI();

        try {
            executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, collUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, SyntaxException, LockException {
                            final Permission permission = collection.getPermissionsNoLock();
                            permission.setGroup(group);
                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + collUri.toString() + "'", e);
        }
    }

    @Override
    public void chown(final Account u) throws XMLDBException {
        final XmldbURI collUri = collection.getPathURI();

        try {
            executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, collUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, SyntaxException, LockException {
                            final Permission permission = collection.getPermissionsNoLock();
                            permission.setOwner(u);
                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + collUri.toString() + "'", e);
        }
    }

    @Override
    public void chown(final Account u, final String group) throws XMLDBException {
        final XmldbURI collUri = collection.getPathURI();
       
        try {
             executeWithBroker(new BrokerOperation<Void>() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyCollection(broker, collUri, new DatabaseItemModifier<org.exist.collections.Collection, Void>() {
                        @Override
                        public Void modify(org.exist.collections.Collection collection) throws PermissionDeniedException, SyntaxException, LockException {
                            final Permission permission = collection.getPermissionsNoLock();
                            permission.setOwner(u);
                            permission.setGroup(group);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Collection '" + collUri.toString() + "'", e);
        }
    }

    @Override
    public void chgrp(final Resource resource, final String group) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            document.getPermissions().setGroup(group);
                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }

    }

    @Override
    public void chown(final Resource resource, final Account u) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            document.getPermissions().setOwner(u);
                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
        }

    }

    @Override
    public void chown(final Resource resource, final Account u, final String group) throws XMLDBException {
  try {
             executeWithBroker(new BrokerOperation() {
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>() {
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, LockException {
                            document.getPermissions().setOwner(u);
                            document.getPermissions().setGroup(group);
                            return null;
                        }
                    });
                }
             });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to modify permission on Resource '" + resource.getId() + "'", e);
       

    }

  /* (non-Javadoc)
   * @see org.exist.xmldb.UserManagementService#hasUserLock(org.xmldb.api.base.Resource)
   */
    @Override
    public String hasUserLock(final Resource res) throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<String>(){
                @Override
                public String withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return readResource(broker, res, new DatabaseItemReader<DocumentImpl, String>(){
                        @Override
                        public String read(DocumentImpl document) {
                            final Account lockOwner = document.getUserLock();
                            return lockOwner == null ? null : lockOwner.getName();
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
 
    @Override
    public void lockResource(final Resource resource, final Account u) throws XMLDBException {
       
        final String resourceId = resource.getId();
       
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>(){
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, SyntaxException, LockException {
                            if(!document.getPermissions().validate(user, Permission.WRITE)) {
                                throw new PermissionDeniedException("User is not allowed to lock resource " + resourceId);
                            }

                            final SecurityManager manager = broker.getBrokerPool().getSecurityManager();
                            if(!(user.equals(u) || manager.hasAdminPrivileges(user))) {
                                throw new PermissionDeniedException("User " + user.getName() + " is not allowed to lock resource '" + resourceId + "' for user " + u.getName());
                            }

                            final Account lockOwner = document.getUserLock();

                            if(lockOwner != null) {
                                if(lockOwner.equals(u)) {
                                    return null;
                                } else if(!manager.hasAdminPrivileges(user)) {
                                    throw new PermissionDeniedException("Resource '" + resourceId + "' is already locked by user " + lockOwner.getName());
                                }
                            }

                            document.setUserLock(u);

                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Unable to lock resource '" + resourceId + "': " + e.getMessage(), e);
        }
    }
 
    @Override
    public void unlockResource(final Resource resource) throws XMLDBException {
       
        final String resourceId = resource.getId();
       
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return modifyResource(broker, resource, new DatabaseItemModifier<DocumentImpl, Void>(){
                        @Override
                        public Void modify(DocumentImpl document) throws PermissionDeniedException, SyntaxException, LockException {
                            if(!document.getPermissions().validate(user, Permission.WRITE)) {
        throw new PermissionDeniedException("User is not allowed to lock resource '" + resourceId + "'");
                            }
     
                           
                            final Account lockOwner = document.getUserLock();
     
                            final SecurityManager manager = broker.getBrokerPool().getSecurityManager();
                            if(lockOwner != null && !(lockOwner.equals(user) || manager.hasAdminPrivileges(user))) {
                                throw new PermissionDeniedException("Resource '" + resourceId + "' is already locked by user " + lockOwner.getName());
                            }
                           
                            document.setUserLock(null);
                           
                            return null;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Unable to unlock resource '" + resourceId + "': " + e.getMessage(), e);
        }   
    }

    @Override
    public Permission getPermissions(Collection coll) throws XMLDBException {
        if(coll instanceof LocalCollection) {
            return ((LocalCollection) coll).getCollection().getPermissionsNoLock();
        }
        return null;
    }

    @Override
    public Permission getSubCollectionPermissions(final Collection parent, final String name) throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<Permission>(){
                @Override
                public Permission withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    if(parent instanceof LocalCollection) {
                        return ((LocalCollection) parent).getCollection().getSubCollectionEntry(broker, name).getPermissions();
                    }
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e);
        }   
    }

    @Override
    public Permission getSubResourcePermissions(final Collection parent, final String name) throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<Permission>(){
                @Override
                public Permission withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    if(parent instanceof LocalCollection) {
                        return ((LocalCollection) parent).getCollection().getResourceEntry(broker, name).getPermissions();
                    }
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e);
        }
    }

    @Override
    public Date getSubCollectionCreationTime(final Collection parent, final String name) throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<Date>(){
                @Override
                public Date withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    if(parent instanceof LocalCollection) {
                        return new Date(((LocalCollection) parent).getCollection().getSubCollectionEntry(broker, name).getCreated());
                    }
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e);
        }
    }
   
   
   

    @Override
    public Permission getPermissions(final Resource resource) throws XMLDBException {
       
        try {
            return executeWithBroker(new BrokerOperation<Permission>() {
                @Override
                public Permission withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return readResource(broker, resource, new DatabaseItemReader<DocumentImpl, Permission>(){
                        @Override
                        public Permission read(DocumentImpl document) {
                            return document.getPermissions();
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public Permission[] listResourcePermissions() throws XMLDBException {
       
        final XmldbURI collectionUri = collection.getPathURI();
        try {
            return executeWithBroker(new BrokerOperation<Permission[]>() {
                @Override
                public Permission[] withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return readCollection(broker, collectionUri, new DatabaseItemReader<org.exist.collections.Collection, Permission[]>(){
                        @Override
                        public Permission[] read(org.exist.collections.Collection collection) throws PermissionDeniedException {
                            if(!collection.getPermissionsNoLock().validate(user, Permission.READ)) {
                                    return new Permission[0];
                            }
                           
                            final Permission perms[] = new Permission[collection.getDocumentCount(broker)];                           
                            final Iterator<DocumentImpl> itDocument = collection.iterator(broker);
                            int i = 0;
                            while(itDocument.hasNext()) {
                                final DocumentImpl document = itDocument.next();
                                perms[i++] = document.getPermissions();
                            }

                            return perms;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }  
    }

    @Override
    public Permission[] listCollectionPermissions() throws XMLDBException {
       
        final XmldbURI collectionUri = collection.getPathURI();
        try {
            return executeWithBroker(new BrokerOperation<Permission[]>() {
                @Override
                public Permission[] withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    return readCollection(broker, collectionUri, new DatabaseItemReader<org.exist.collections.Collection, Permission[]>(){
                        @Override
                        public Permission[] read(org.exist.collections.Collection collection) throws XMLDBException, PermissionDeniedException {
                            if(!collection.getPermissionsNoLock().validate(user, Permission.READ)) {
        return new Permission[0];
                            }
                           
                            final Permission perms[] = new Permission[collection.getChildCollectionCount(broker)];
                            final Iterator<XmldbURI> itChildCollectionUri = collection.collectionIterator(broker);
                            int i = 0;
                            while(itChildCollectionUri.hasNext()) {
                                final XmldbURI childCollectionUri = collectionUri.append(itChildCollectionUri.next());
                                Permission childPermission = readCollection(broker, childCollectionUri, new DatabaseItemReader<org.exist.collections.Collection, Permission>(){
                                    @Override
                                    public Permission read(org.exist.collections.Collection childCollection) {
                                        return childCollection.getPermissionsNoLock();
                                    }
                                });
                                perms[i++] = childPermission;
                            }
                           
      return perms;
                        }
                    });
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }    
    }

    @Override
    public Account getAccount(final String name) throws XMLDBException {
       
        try {
            return executeWithBroker(new BrokerOperation<Account>(){

                @Override
                public Account withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    return sm.getAccount(name);
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public Account[] getAccounts() throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<Account[]>(){

                @Override
                public Account[] withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    final java.util.Collection<Account> users = sm.getUsers();
                    return users.toArray(new Account[users.size()]);
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public Group getGroup(final String name) throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<Group>(){

                @Override
                public Group withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    return sm.getGroup(name);
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public String[] getGroups() throws XMLDBException {
        try {
            return executeWithBroker(new BrokerOperation<String[]>(){

                @Override
                public String[] withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    final java.util.Collection<Group> groups = sm.getGroups();
                    final String[] groupNames = new String[groups.size()];
                    int i = 0;
                    for (final Group group : groups) {
                        groupNames[i++] = group.getName();
                    }
                    return groupNames;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public void removeAccount(final Account u) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){

                @Override
                public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    if(!sm.hasAdminPrivileges(user))
                      {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "you are not allowed to remove users");}
         
                    sm.deleteAccount(u);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public void removeGroup(final Group group) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
         
                    sm.deleteGroup(group.getName());
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public void setCollection(Collection collection) throws XMLDBException {
        this.collection = (LocalCollection) collection;
    }

   

    @Override
    public void updateAccount(final Account u) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){

                @Override
                public Void withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
         
                    sm.updateAccount(u);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
   
    @Override
    public void updateGroup(final Group g) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){

                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
         
                    sm.updateGroup(g);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public String[] getGroupMembers(final String groupName) throws XMLDBException {
        try {
            final List<String> groupMembers = executeWithBroker(new BrokerOperation<List<String>>(){
                @Override
                public List<String> withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                   
                    return sm.findAllGroupMembers(groupName);
                }
            });
           
            return groupMembers.toArray(new String[groupMembers.size()]);
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
   
    @Override
    public void addAccountToGroup(final String accountName, final String groupName) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                    final Account account = sm.getAccount(accountName);
                    account.addGroup(groupName);
                    sm.updateAccount(account);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
   
    @Override
    public void addGroupManager(final String manager, final String groupName) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                   
                    final Account account = sm.getAccount(manager);
                    final Group group = sm.getGroup(groupName);
                    group.addManager(account);
                    sm.updateGroup(group);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
   
    @Override
    public void removeGroupManager(final String groupName, final String manager) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                   
                    final Group group = sm.getGroup(groupName);
                    final Account account = sm.getAccount(manager);
                    group.removeManager(account);
                    sm.updateGroup(group);
                   
                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }
 
    @Override
    public void addUserGroup(Account user) throws XMLDBException
    }
 
    @Override
    public void removeGroupMember(final String group, final String member) throws XMLDBException {
        try {
            executeWithBroker(new BrokerOperation<Void>(){
                @Override
                public Void withBroker(final DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
                    final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
                   
                    final Account account = sm.getAccount(member);
                    account.remGroup(group);
                    sm.updateAccount(account);

                    return null;
                }
            });
        } catch(final Exception e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
        }
    }

    @Override
    public void addUser(User user) throws XMLDBException {
        final Account account = new UserAider(user.getName());
        addAccount(account);
    }

    @Override
    public void updateUser(User user) throws XMLDBException {
        final Account account = new UserAider(user.getName());
        account.setPassword(user.getPassword());
        //TODO: groups
        updateAccount(account);
    }

    @Override
    public User getUser(String name) throws XMLDBException {
        return getAccount(name);
    }

    @Override
    public User[] getUsers() throws XMLDBException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void removeUser(User user) throws XMLDBException {
        // TODO Auto-generated method stub 
    }

    @Override
    public void lockResource(Resource res, User u) throws XMLDBException {
        final Account account = new UserAider(u.getName());
        lockResource(res, account);
    }
       
    @Override
    public String getProperty(String property) throws XMLDBException {
        return null;
    }
   
    @Override
    public void setProperty(String property, String value) throws XMLDBException {
    }

    private interface BrokerOperation<R> {
        public R withBroker(DBBroker broker) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException;
    }

    private <R> R executeWithBroker(BrokerOperation<R> brokerOperation) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
      final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
        broker = pool.get(user);
       
        return brokerOperation.withBroker(broker);
       
    } finally {
        if(broker != null)
            {pool.release(broker);}
       
        if(preserveSubject != null)
          {pool.setSubject(preserveSubject);}
    }
    }
   
    private <R> R readResource(DBBroker broker, Resource resource, DatabaseItemReader<DocumentImpl, R> reader) throws XMLDBException, PermissionDeniedException {
       
        DocumentImpl document = null;   
        try {
            document = ((AbstractEXistResource) resource).openDocument(broker, Lock.READ_LOCK);
               
            return reader.read(document);
               
        } finally {
            if(document != null) {
                ((AbstractEXistResource) resource).closeDocument(document, Lock.READ_LOCK);
            }
        }
    }
   
    private <R> R readCollection(DBBroker broker, XmldbURI collectionURI, DatabaseItemReader<org.exist.collections.Collection, R> reader) throws XMLDBException, PermissionDeniedException {
        org.exist.collections.Collection coll = null;
       
        try {
            coll = broker.openCollection(collectionURI, Lock.READ_LOCK);
            if(coll == null) {
                throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "Collection " + collectionURI.toString() + " not found");
            }
           
            return reader.read(coll);
           
        } finally {
            if(coll != null) {
                coll.release(Lock.READ_LOCK);
            }
        }
    }
   
    private <R> R modifyResource(DBBroker broker, Resource resource, DatabaseItemModifier<DocumentImpl, R> modifier) throws XMLDBException, LockException, PermissionDeniedException, EXistException, SyntaxException {
        final TransactionManager transact = broker.getBrokerPool().getTransactionManager();
        final Txn transaction = transact.beginTransaction();
       
        DocumentImpl document = null;
        try {
            document = ((AbstractEXistResource) resource).openDocument(broker, Lock.WRITE_LOCK);
            final SecurityManager sm = broker.getBrokerPool().getSecurityManager();
            if(!document.getPermissions().validate(user, Permission.WRITE) && !sm.hasAdminPrivileges(user)) {
                throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "you are not the owner of this resource; owner = " + document.getPermissions().getOwner());
            }
           
            final R result = modifier.modify(document);
           
            broker.storeXMLResource(transaction, document);
            transact.commit(transaction);
           
            return result;
           
        } catch(final EXistException ee) {
            transact.abort(transaction);
            throw ee;
        } catch(final XMLDBException xmldbe) {
            transact.abort(transaction);
            throw xmldbe;
        } catch(final LockException le) {
            transact.abort(transaction);
            throw le;
        } catch(final PermissionDeniedException pde) {
            transact.abort(transaction);
            throw pde;
        } catch(final SyntaxException se) {
            transact.abort(transaction);
            throw se;
        } finally {
            transact.close(transaction);
            if(document != null) {
                ((AbstractEXistResource)resource).closeDocument(document, Lock.WRITE_LOCK);
            }
        }
    }
   
    private <R> R modifyCollection(DBBroker broker, XmldbURI collectionURI, DatabaseItemModifier<org.exist.collections.Collection, R> modifier) throws XMLDBException, LockException, PermissionDeniedException, IOException, EXistException, TriggerException, SyntaxException {
        final TransactionManager transact = broker.getBrokerPool().getTransactionManager();
        final Txn transaction = transact.beginTransaction();
       
        org.exist.collections.Collection coll = null;
       
        try {
            coll = broker.openCollection(collectionURI, Lock.WRITE_LOCK);
            if(coll == null) {
                throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "Collection " + collectionURI.toString() + " not found");
            }
           
            final R result = modifier.modify(coll);
           
            broker.saveCollection(transaction, coll);
            transact.commit(transaction);
            broker.flush();
           
            return result;
           
        } catch(final EXistException ee) {
            transact.abort(transaction);
            throw ee;
        } catch(final XMLDBException xmldbe) {
            transact.abort(transaction);
            throw xmldbe;
        } catch(final LockException le) {
            transact.abort(transaction);
            throw le;
        } catch(final PermissionDeniedException pde) {
            transact.abort(transaction);
            throw pde;
        } catch(final IOException ioe) {
            transact.abort(transaction);
            throw ioe;
        } catch(final TriggerException te) {
            transact.abort(transaction);
            throw te;
        } catch(final SyntaxException se) {
            transact.abort(transaction);
            throw se;
        } finally {
            transact.close(transaction);
            if(coll != null) {
                coll.release(Lock.WRITE_LOCK);
            }
        }
    }
   
    private interface DatabaseItemModifier<T, R> {
        public R modify(T databaseItem) throws PermissionDeniedException, SyntaxException, LockException;
    }
   
    private interface DatabaseItemReader<T, R> {
        public R read(T databaseItem) throws PermissionDeniedException, XMLDBException;
    }
}
TOP

Related Classes of org.exist.xmldb.LocalUserManagementService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.