package org.exist.xmldb;
import java.io.IOException;
import java.util.Iterator;
import org.exist.EXistException;
import org.exist.dom.DocumentImpl;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.security.User;
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;
/*************************************************
* Modified by {Marco.Tampucci, Massimo.Martinelli} @isti.cnr.it
**************************************/
public class LocalUserManagementService implements UserManagementService {
private LocalCollection collection;
private BrokerPool pool;
private User user;
public LocalUserManagementService(
User user,
BrokerPool pool,
LocalCollection collection) {
this.pool = pool;
this.collection = collection;
this.user = user;
}
public void addUser(User u) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if (!manager.hasAdminPrivileges(user))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
" you are not allowed to change this user");
if (manager.hasUser(u.getName()))
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
"user " + u.getName() + " exists");
manager.setUser(u);
}
public void setPermissions(Resource resource, Permission perm)
throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
DocumentImpl document = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
document = ((AbstractEXistResource) resource).openDocument(broker, Lock.WRITE_LOCK);
if (!document.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not the owner of this resource; owner = "
+ document.getPermissions().getOwner());
document.setPermissions(perm);
if (!manager.hasGroup(perm.getOwnerGroup()))
manager.addGroup(perm.getOwnerGroup());
broker.storeXMLResource(transaction, document);
transact.commit(transaction);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource)resource).closeDocument(document, Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void setPermissions(Collection child, Permission perm) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
org.exist.collections.Collection coll = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
coll = broker.openCollection(XmldbURI.create(child.getName()), Lock.WRITE_LOCK);
if(coll == null) {
throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "Collection " + child.getName() + " not found");
}
if(!coll.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "you are not the owner of this collection");
}
if(!manager.hasGroup(perm.getOwnerGroup())) {
manager.addGroup(perm.getOwnerGroup());
}
coll.setPermissions(perm);
broker.saveCollection(transaction, coll);
transact.commit(transaction);
broker.flush();
} catch (IOException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
} catch (PermissionDeniedException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, e.getMessage(), e);
} catch (LockException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to acquire lock on collections.dbx", e);
} finally {
if(coll != null) {
coll.release(Lock.WRITE_LOCK);
}
pool.release(broker);
}
}
public void chmod(String modeStr) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
org.exist.collections.Collection coll = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
coll = broker.openCollection(collection.getPathURI(), Lock.WRITE_LOCK);
if(coll == null)
throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "Collection " + collection.getPath() +
" not found");
if (!coll.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not the owner of this collection");
}
coll.setPermissions(modeStr);
broker.saveCollection(transaction, coll);
transact.commit(transaction);
broker.flush();
} catch (SyntaxException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (LockException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
"Failed to acquire lock on collections.dbx",
e);
} catch (IOException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (PermissionDeniedException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
e.getMessage(),
e);
} finally {
if(coll != null)
coll.release(Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void chmod(Resource resource, int mode) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
DocumentImpl document = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
document = ((AbstractEXistResource) resource).openDocument(broker, Lock.WRITE_LOCK);
if (!document.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not the owner of this resource");
}
document.setPermissions(mode);
broker.storeXMLResource(transaction, document);
transact.commit(transaction);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource) resource).closeDocument(document, Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void chmod(int mode) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
org.exist.collections.Collection coll = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
coll = broker.openCollection(collection.getPathURI(), Lock.WRITE_LOCK);
if(coll == null)
throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "Collection " + collection.getPath() +
" not found");
if (!coll.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not the owner of this collection");
}
coll.setPermissions(mode);
broker.saveCollection(transaction, coll);
transact.commit(transaction);
broker.flush();
} catch (IOException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (PermissionDeniedException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
e.getMessage(),
e);
} catch (LockException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
"Failed to acquire lock on collections.dbx",
e);
} finally {
if(coll != null)
coll.release(Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void chmod(Resource resource, String modeStr)
throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
DocumentImpl document = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
document = ((AbstractEXistResource) resource).openDocument(broker, Lock.WRITE_LOCK);
if (!document.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not the owner of this resource");
}
document.setPermissions(modeStr);
broker.storeXMLResource(transaction, document);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (SyntaxException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource) resource).closeDocument(document, Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void chown(User u, String group) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if (!manager.hasUser(u.getName()))
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Unknown user: " + u.getName());
if (!manager.hasAdminPrivileges(user))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"need admin privileges for chown");
org.exist.collections.Collection coll = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
coll = broker.openCollection(collection.getPathURI(), Lock.WRITE_LOCK);
coll.getPermissions().setOwner(u);
if (!manager.hasGroup(group))
manager.addGroup(group);
coll.getPermissions().setGroup(group);
broker.saveCollection(transaction, coll);
transact.commit(transaction);
broker.flush();
//broker.sync();
} catch (IOException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} catch (PermissionDeniedException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
e.getMessage(),
e);
} finally {
if(coll != null)
coll.release(Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void chown(Resource res, User u, String group)
throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if (!manager.hasUser(u.getName()))
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Unknown user");
if (!manager.hasAdminPrivileges(user))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"need admin privileges for chown");
DocumentImpl document = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
document = ((AbstractEXistResource) res).openDocument(broker, Lock.WRITE_LOCK);
Permission perm = document.getPermissions();
perm.setOwner(u);
if (!manager.hasGroup(group))
manager.addGroup(group);
perm.setGroup(group);
broker.storeXMLResource(transaction, document);
transact.commit(transaction);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource) res).closeDocument(document, Lock.WRITE_LOCK);
pool.release(broker);
}
}
/* (non-Javadoc)
* @see org.exist.xmldb.UserManagementService#hasUserLock(org.xmldb.api.base.Resource)
*/
public String hasUserLock(Resource res) throws XMLDBException {
DocumentImpl doc = null;
DBBroker broker = null;
try {
broker = pool.get(user);
doc = ((AbstractEXistResource) res).openDocument(broker, Lock.READ_LOCK);
User lockOwner = doc.getUserLock();
return lockOwner == null ? null : lockOwner.getName();
} catch (EXistException e) {
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource) res).closeDocument(doc, Lock.READ_LOCK);
pool.release(broker);
}
}
public void lockResource(Resource res, User u) throws XMLDBException {
DocumentImpl doc = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
doc = ((AbstractEXistResource) res).openDocument(broker, Lock.WRITE_LOCK);
if (!doc.getPermissions().validate(user, Permission.UPDATE))
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
"User is not allowed to lock resource " + res.getId());
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if(!(user.equals(u) || manager.hasAdminPrivileges(user))) {
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
"User " + user.getName() + " is not allowed to lock resource for " +
"user " + u.getName());
}
User lockOwner = doc.getUserLock();
if(lockOwner != null) {
if(lockOwner.equals(u))
return;
else if(!manager.hasAdminPrivileges(user))
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
"Resource is already locked by user " + lockOwner.getName());
}
doc.setUserLock(u);
broker.storeXMLResource(transaction, doc);
transact.commit(transaction);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
e.getMessage(), e);
} finally {
((AbstractEXistResource) res).closeDocument(doc, Lock.WRITE_LOCK);
pool.release(broker);
}
}
public void unlockResource(Resource res) throws XMLDBException {
DocumentImpl doc = null;
DBBroker broker = null;
TransactionManager transact = pool.getTransactionManager();
Txn transaction = transact.beginTransaction();
try {
broker = pool.get(user);
doc = ((AbstractEXistResource) res).openDocument(broker, Lock.WRITE_LOCK);
if (!doc.getPermissions().validate(user, Permission.UPDATE))
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
"User is not allowed to lock resource " + res.getId());
org.exist.security.SecurityManager manager = pool.getSecurityManager();
User lockOwner = doc.getUserLock();
if(lockOwner != null && !(lockOwner.equals(user) || manager.hasAdminPrivileges(user))) {
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
"Resource is already locked by user " + lockOwner.getName());
}
doc.setUserLock(null);
broker.storeXMLResource(transaction, doc);
transact.commit(transaction);
} catch (EXistException e) {
transact.abort(transaction);
throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
e.getMessage(), e);
} finally {
((AbstractEXistResource) res).closeDocument(doc, Lock.WRITE_LOCK);
pool.release(broker);
}
}
public String getName() {
return "UserManagementService";
}
public Permission getPermissions(Collection coll) throws XMLDBException {
if (coll instanceof LocalCollection)
return ((LocalCollection) coll).getCollection().getPermissions();
return null;
}
public Permission getPermissions(Resource resource) throws XMLDBException {
DBBroker broker = null;
DocumentImpl doc = null;
try {
broker = pool.get(user);
doc = ((AbstractEXistResource) resource).openDocument(broker, Lock.READ_LOCK);
return doc.getPermissions();
} catch (EXistException e) {
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
((AbstractEXistResource) resource).closeDocument(doc, Lock.READ_LOCK);
pool.release(broker);
}
}
public Permission[] listResourcePermissions() throws XMLDBException {
DBBroker broker = null;
org.exist.collections.Collection c = null;
try {
broker = pool.get(user);
c = broker.openCollection(collection.getPathURI(), Lock.READ_LOCK);
if (!c .getPermissions().validate(user, Permission.READ))
return new Permission[0];
Permission perms[] =
new Permission[c.getDocumentCount()];
int j = 0;
DocumentImpl doc;
for (Iterator i = c.iterator(broker); i.hasNext(); j++) {
doc = (DocumentImpl) i.next();
perms[j] = doc.getPermissions();
}
return perms;
} catch (EXistException e) {
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
if(c != null)
c.release(Lock.READ_LOCK);
pool.release(broker);
}
}
public Permission[] listCollectionPermissions() throws XMLDBException {
DBBroker broker = null;
org.exist.collections.Collection c = null;
try {
broker = pool.get(user);
c = broker.openCollection(collection.getPathURI(), Lock.READ_LOCK);
if (!c.getPermissions().validate(user, Permission.READ))
return new Permission[0];
Permission perms[] =
new Permission[c.getChildCollectionCount()];
XmldbURI child;
org.exist.collections.Collection childColl;
int j = 0;
for (Iterator i = c.collectionIterator(); i.hasNext(); j++) {
child = (XmldbURI) i.next();
childColl =
broker.openCollection(collection.getPathURI().append(child), Lock.READ_LOCK);
if(childColl != null) {
try {
perms[j] = childColl.getPermissions();
} finally {
childColl.release(Lock.READ_LOCK);
}
}
}
return perms;
} catch (EXistException e) {
throw new XMLDBException(
ErrorCodes.VENDOR_ERROR,
e.getMessage(),
e);
} finally {
if(c != null)
c.release(Lock.READ_LOCK);
pool.release(broker);
}
}
public String getProperty(String property) throws XMLDBException {
return null;
}
public User getUser(String name) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
return manager.getUser(name);
}
public User[] getUsers() throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
return manager.getUsers();
}
public String[] getGroups() throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
return manager.getGroups();
}
public String getVersion() {
return "1.0";
}
public void removeUser(User u) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if (!manager.hasAdminPrivileges(user))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"you are not allowed to remove users");
try {
manager.deleteUser(u);
} catch (PermissionDeniedException e) {
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"unable to remove user " + u.getName(),
e);
}
}
public void setCollection(Collection collection) throws XMLDBException {
this.collection = (LocalCollection) collection;
}
public void setProperty(String property, String value)
throws XMLDBException {
}
public void updateUser(User u) throws XMLDBException {
org.exist.security.SecurityManager manager = pool.getSecurityManager();
if (!(u.getName().equals(user.getName())
|| manager.hasAdminPrivileges(user)))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
" you are not allowed to change this user");
User old = manager.getUser(u.getName());
if (old == null)
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"user " + u.getName() + " does not exist");
String[] groups = u.getGroups();
for (int i = 0; i < groups.length; i++) {
if(!(old.hasGroup(groups[i]) || manager.hasAdminPrivileges(user)))
throw new XMLDBException(
ErrorCodes.PERMISSION_DENIED,
"not allowed to change group memberships");
}
u.setUID(old.getUID());
manager.setUser(u);
}
public void addUserGroup(User user) throws XMLDBException {
}
public void removeGroup(User user, String rmgroup) throws XMLDBException {
}
}