X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/4d73777015fc9d46e2e9ef8352a54545f09809e0..edf24a219b6250df205df847504860bc7892f81b:/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java diff --git a/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java b/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java index 6319790..0cb2971 100644 --- a/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java +++ b/src/gr/ebs/gss/server/ejb/ExternalAPIBean.java @@ -31,6 +31,7 @@ import gr.ebs.gss.server.domain.FileTag; import gr.ebs.gss.server.domain.FileUploadStatus; import gr.ebs.gss.server.domain.Folder; import gr.ebs.gss.server.domain.Group; +import gr.ebs.gss.server.domain.Invitation; import gr.ebs.gss.server.domain.Nonce; import gr.ebs.gss.server.domain.Permission; import gr.ebs.gss.server.domain.User; @@ -56,12 +57,14 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Random; import java.util.Set; import java.util.StringTokenizer; import javax.ejb.EJB; import javax.ejb.EJBException; +import javax.ejb.EJBTransactionRolledbackException; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; @@ -73,10 +76,10 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.QueueConnectionFactory; import javax.jms.Session; -import javax.jws.WebMethod; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; +import javax.persistence.PersistenceException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -97,12 +100,19 @@ import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hibernate.exception.ConstraintViolationException; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import com.novell.ldap.LDAPAttribute; +import com.novell.ldap.LDAPAttributeSet; +import com.novell.ldap.LDAPConnection; +import com.novell.ldap.LDAPEntry; +import com.novell.ldap.LDAPException; + /** * The concrete implementation of the ExternalAPI interface. * @@ -138,6 +148,20 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { */ private static Random random = new Random(); + /** + * Mark the folder and all of its parent folders as modified from the specified user. + */ + private void touchParentFolders(Folder folder, User user, Date date) { + Folder f = folder; + while (f != null) { + AuditInfo ai = f.getAuditInfo(); + ai.setModifiedBy(user); + ai.setModificationDate(date); + f.setAuditInfo(ai); + f = f.getParent(); + } + } + @Override public FolderDTO getRootFolder(Long userId) throws ObjectNotFoundException { if (userId == null) @@ -146,11 +170,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return folder.getDTO(); } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#getFolder(java.lang.Long) - */ + @Override public FolderDTO getFolder(final Long userId, final Long folderId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -263,7 +283,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public void createFolder(Long userId, Long parentId, String name) + public FolderDTO createFolder(Long userId, Long parentId, String name) throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException { // Validate. if (userId == null) @@ -290,7 +310,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { " to write to this folder"); // Do the actual work. - createFolder(name, parent, creator); + return createFolder(name, parent, creator); } /** @@ -299,8 +319,9 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @param name * @param parent * @param creator + * @return the new folder */ - private void createFolder(String name, Folder parent, User creator) { + private FolderDTO createFolder(String name, Folder parent, User creator) { Folder folder = new Folder(); folder.setName(name); if (parent != null) { @@ -316,6 +337,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { auditInfo.setModifiedBy(creator); auditInfo.setModificationDate(now); folder.setAuditInfo(auditInfo); + touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate()); if (parent != null) for (Permission p : parent.getPermissions()) { @@ -336,6 +358,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { folder.addPermission(permission); } dao.create(folder); + return folder.getDTO(); } /* @@ -365,6 +388,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { removeSubfolderFiles(folder); parent.removeSubfolder(folder); dao.delete(folder); + touchParentFolders(parent, user, new Date()); } /** @@ -405,30 +429,41 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public void modifyFolder(Long userId, Long folderId, String folderName) - throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException { + public FolderDTO updateFolder(Long userId, Long folderId, String folderName, + Set permissions) + throws InsufficientPermissionsException, ObjectNotFoundException, + DuplicateNameException { // Validate. if (userId == null) throw new ObjectNotFoundException("No user specified"); if (folderId == null) throw new ObjectNotFoundException("No folder specified"); - if (StringUtils.isEmpty(folderName)) - throw new ObjectNotFoundException("New folder name is empty"); Folder folder = dao.getEntityById(Folder.class, folderId); User user = dao.getEntityById(User.class, userId); - if (!folder.hasWritePermission(user)) + if (folderName != null && !folder.hasWritePermission(user)) + throw new InsufficientPermissionsException("You don't have the necessary permissions"); + if(permissions != null && !permissions.isEmpty() && !folder.hasModifyACLPermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); Folder parent = folder.getParent(); - if (parent != null) - if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName)) - throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level"); + if (folderName != null) { + if (parent != null) + if (!folder.getName().equals(folderName) && dao.existsFolderOrFile(parent.getId(), folderName)) + throw new DuplicateNameException("A folder or file with the name '" + folderName + "' already exists at this level"); + + // Do the actual modification. + folder.setName(folderName); + } + if (permissions != null) + setFolderPermissions(user, folder, permissions); - // Do the actual modification. - folder.setName(folderName); + folder.getAuditInfo().setModificationDate(new Date()); + folder.getAuditInfo().setModifiedBy(user); dao.update(folder); + touchParentFolders(folder, user, new Date()); + return folder.getDTO(); } /* @@ -443,6 +478,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No user specified"); if (StringUtils.isEmpty(name)) throw new ObjectNotFoundException("New group name is empty"); + if (name.indexOf('/')>=0) + throw new IllegalArgumentException("Character '/' is not allowed in group name"); if (dao.existsGroup(userId, name)) throw new DuplicateNameException("A group with the name '" + name + "' already exists"); @@ -593,6 +630,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { for (final FileBody body : file.getBodies()) deleteActualFile(body.getStoredFilePath()); dao.delete(file); + touchParentFolders(parent, user, new Date()); indexFile(fileId, true); } @@ -604,12 +642,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { logger.error("Could not delete file " + filePath); } - /* - * (non-Javadoc) - * - * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long, - * java.lang.Long, java.lang.String) - */ public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException { if (userId == null) throw new ObjectNotFoundException("No user specified"); @@ -620,34 +652,55 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { final User user = dao.getEntityById(User.class, userId); final FileHeader fh = dao.getEntityById(FileHeader.class, fileHeaderId); + final Folder parent = fh.getFolder(); + if (parent == null) + throw new ObjectNotFoundException("The specified file has no parent folder"); user.addTag(fh, tag); + touchParentFolders(parent, user, new Date()); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUserTags(java.lang.Long) - */ - @WebMethod(operationName = "getUserTags") public Set getUserTags(final Long userId) throws ObjectNotFoundException { return dao.getUserTags(userId); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#updateFile(java.lang.Long, java.lang.Long, java.lang.String, java.util.Set) - */ - public void updateFile(Long userId, Long fileId, String name, String tagSet) throws ObjectNotFoundException, InsufficientPermissionsException { + public void updateFile(Long userId, Long fileId, String name, + String tagSet, Date modificationDate, Boolean versioned, + Boolean readForAll, Set permissions) + throws DuplicateNameException, ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (fileId == null) throw new ObjectNotFoundException("No file specified"); FileHeader file = dao.getEntityById(FileHeader.class, fileId); - User user = dao.getEntityById(User.class, userId); - if (!file.hasWritePermission(user)) - throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")"); + final Folder parent = file.getFolder(); + if (parent == null) + throw new ObjectNotFoundException("The specified file has no parent folder"); - if (name != null) + User user = dao.getEntityById(User.class, userId); + // Check permissions for modifying the file metadata. + if ((name != null || tagSet != null || modificationDate != null || versioned != null) && !file.hasWritePermission(user)) + throw new InsufficientPermissionsException("User " + user.getId() + " cannot update file " + file.getName() + "(" + file.getId() + ")"); + // Check permissions for making file public. + if (readForAll != null && !user.equals(file.getOwner())) + throw new InsufficientPermissionsException("Only the owner can make a file public or not public"); + // Check permissions for modifying the ACL. + if(permissions != null && !permissions.isEmpty() && !file.hasModifyACLPermission(user)) + throw new InsufficientPermissionsException("User " + user.getId() + " cannot update the permissions on file " + file.getName() + "(" + file.getId() + ")"); + + if (name != null) { + // Do plain check for file already exists. + // Extreme concurrency case should be caught by constraint violation later. + if (dao.existsFolderOrFile(parent.getId(), name)) throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists"); file.setName(name); - List tags = file.getFileTags(); + } + if (modificationDate != null) + file.getAuditInfo().setModificationDate(modificationDate); + else + file.getAuditInfo().setModificationDate(new Date()); + file.getAuditInfo().setModifiedBy(user); + + List tags = file.getFileTags(); if (tagSet != null) { Iterator i = tags.iterator(); while (i.hasNext()) { @@ -662,6 +715,32 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { while (st.hasMoreTokens()) new FileTag(user, file, st.nextToken().trim()); } + if (versioned != null && !file.isVersioned() == versioned) { + if (file.isVersioned()) + removeOldVersions(userId, fileId); + file.setVersioned(versioned); + } + if (readForAll != null && user.equals(file.getOwner())) + file.setReadForAll(readForAll); + if (permissions != null && !permissions.isEmpty()) + setFilePermissions(file, permissions); + + /* + * Force constraint violation to manifest itself here. + * This should cover extreme concurrency cases that the simple check + * above hasn't caught. + */ + try { + dao.flush(); + } + catch (EJBTransactionRolledbackException e) { + Throwable cause = e.getCause(); + if (cause instanceof PersistenceException && cause.getCause() instanceof ConstraintViolationException) + throw new DuplicateNameException("A file or folder with the name '" + name + "' already exists"); + throw e; + } + + touchParentFolders(parent, user, new Date()); // Re-index the file if it was modified. if (name != null || tagSet != null) @@ -896,6 +975,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { User user = dao.getEntityById(User.class, userId); if (!file.hasReadPermission(user) || !destination.hasWritePermission(user)) throw new InsufficientPermissionsException("You don't have the necessary permissions"); + boolean versioned = file.isVersioned(); int versionsNumber = file.getBodies().size(); FileBody oldestBody = file.getBodies().get(0); assert oldestBody != null; @@ -903,6 +983,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { try { createFile(user.getId(), destination.getId(), destName, oldestBody.getMimeType(), new FileInputStream(contents)); FileHeader copiedFile = dao.getFile(destination.getId(), destName); + copiedFile.setVersioned(versioned); dao.flush(); if (versionsNumber > 1) for (int i = 1; i < versionsNumber; i++) { @@ -1075,10 +1156,11 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { file.setDeleted(true); dao.update(file); + touchParentFolders(parent, user, new Date()); } @Override - public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, DuplicateNameException, GSSIOException, QuotaExceededException { + public void moveFileToPath(Long userId, Long ownerId, Long fileId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (ownerId == null) @@ -1107,6 +1189,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new ObjectNotFoundException("No destination file name specified"); FileHeader file = dao.getEntityById(FileHeader.class, fileId); + Folder source = file.getFolder(); Folder destination = dao.getEntityById(Folder.class, destId); User owner = dao.getEntityById(User.class, userId); @@ -1140,10 +1223,12 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } // move the file to the destination folder file.setFolder(destination); + touchParentFolders(source, owner, new Date()); + touchParentFolders(destination, owner, new Date()); } @Override - public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException { + public void moveFolderToPath(Long userId, Long ownerId, Long folderId, String dest) throws ObjectNotFoundException, InsufficientPermissionsException, QuotaExceededException { if (userId == null) throw new ObjectNotFoundException("No user specified"); if (ownerId == null) @@ -1161,16 +1246,62 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public void moveFolder(Long userId, Long folderId, Long destId, String destName) throws ObjectNotFoundException, DuplicateNameException, InsufficientPermissionsException, GSSIOException, QuotaExceededException { - // TODO Simple Move and delete of original folder, in production - // scenario we must first check individual files and folders permissions - copyFolderStructure(userId, folderId, destId, destName); - deleteFolder(userId, folderId); + public void moveFolder(Long userId, Long folderId, Long destId, String destName) + throws ObjectNotFoundException, InsufficientPermissionsException, + QuotaExceededException { + Folder source = dao.getEntityById(Folder.class, folderId); + Folder destination = dao.getEntityById(Folder.class, destId); + User user = dao.getEntityById(User.class, userId); + User sourceOwner = source.getOwner(); + User destinationOwner = destination.getOwner(); + // Do not move trashed folders and contents. + if (source.isDeleted()) + return; + // Check permissions. + if (!destination.hasWritePermission(user) + || !source.hasReadPermission(user) + || !source.hasWritePermission(user)) + throw new InsufficientPermissionsException("You don't have the " + + "necessary permissions"); + // Use the same timestamp for all subsequent modifications to make + // changes appear simultaneous. + Date now = new Date(); + // If source and destination are not in the same user's namespace, + // change owners and check quota. + if (!sourceOwner.equals(destinationOwner)) { + changeOwner(source, destinationOwner, user, now); + if (getQuotaLeft(destinationOwner.getId()) < 0) + throw new QuotaExceededException("Not enough free space " + + "available in destination folder"); + } + // Perform the move. + Folder oldParent = source.getParent(); + oldParent.removeSubfolder(source); + destination.addSubfolder(source); + // Mark the former parent and destination trees upwards as modified. + touchParentFolders(oldParent, user, now); + touchParentFolders(source, user, now); } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getDeletedFiles(java.lang.Long) + /** + * Recursively change the owner of the specified folder and all of its + * contents to the specified owner. Also mark them all as modified with the + * specified modifier and modificationDate. */ + private void changeOwner(Folder folder, User owner, User modifier, Date modificationDate) { + for (FileHeader file: folder.getFiles()) { + file.setOwner(owner); + file.getAuditInfo().setModificationDate(modificationDate); + file.getAuditInfo().setModifiedBy(modifier); + } + for (Folder sub: folder.getSubfolders()) + changeOwner(sub, owner, modifier, modificationDate); + folder.setOwner(owner); + folder.getAuditInfo().setModificationDate(modificationDate); + folder.getAuditInfo().setModifiedBy(modifier); + } + + @Override public List getDeletedFiles(Long userId) throws ObjectNotFoundException { // Validate. if (userId == null) @@ -1204,6 +1335,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { file.setDeleted(false); dao.update(file); + touchParentFolders(parent, user, new Date()); } @Override @@ -1218,6 +1350,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { throw new InsufficientPermissionsException("You don't have the necessary permissions"); folder.setDeleted(true); dao.update(folder); + touchParentFolders(folder, user, new Date()); for (FileHeader file : folder.getFiles()) moveFileToTrash(userId, file.getId()); for (Folder subFolder : folder.getSubfolders()) @@ -1243,6 +1376,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { for (Folder subFolder : folder.getSubfolders()) removeFolderFromTrash(userId, subFolder.getId()); dao.update(folder); + touchParentFolders(folder, user, new Date()); } @Override @@ -1275,7 +1409,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public User createUser(String username, String name, String mail) throws ObjectNotFoundException { + public User createUser(String username, String name, String mail, + String idp, String idpid) throws ObjectNotFoundException { if (username == null) throw new ObjectNotFoundException("No username specified"); if (name == null) @@ -1285,6 +1420,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { user.setUsername(username); user.setName(name); user.setEmail(mail); + user.setIdentityProvider(idp); + user.setIdentityProviderId(idpid); Date now = new Date(); AuditInfo auditInfo = new AuditInfo(); auditInfo.setCreationDate(now); @@ -1311,17 +1448,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } @Override - public User updateUser(String username, String name, String mail) throws ObjectNotFoundException { - if (username == null) - throw new ObjectNotFoundException("No username specified"); - - User user = dao.getUser(username); - user.setName(name); - user.setEmail(mail); - return user; - } - - @Override public User findUser(String username) { if (username == null) return null; @@ -1363,19 +1489,17 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#setFolderPermissions(java.lang.Long, java.lang.Long, java.util.Set) + /** + * Set the provided permissions as the new permissions of the specified + * folder. + * + * @param user + * @param folder + * @param permissions + * @throws ObjectNotFoundException + * @throws InsufficientPermissionsException */ - @Override - public void setFolderPermissions(Long userId, Long folderId, Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (folderId == null) - throw new ObjectNotFoundException("No folder specified"); - User user = dao.getEntityById(User.class, userId); - Folder folder = dao.getEntityById(Folder.class, folderId); - if(!folder.hasModifyACLPermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); + private void setFolderPermissions(User user, Folder folder, Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { // Delete previous entries for (Permission perm: folder.getPermissions()) dao.delete(perm); @@ -1388,10 +1512,14 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { folder.addPermission(getPermission(dto)); } dao.update(folder); - for (FileHeader fh : folder.getFiles()) - setFilePermissions(userId, fh.getId(), fh.isReadForAll(), permissions); + for (FileHeader file : folder.getFiles()) { + setFilePermissions(file, permissions); + Date now = new Date(); + file.getAuditInfo().setModificationDate(now); + file.getAuditInfo().setModifiedBy(user); + } for (Folder sub : folder.getSubfolders()) - setFolderPermissions(userId, sub.getId(), permissions); + setFolderPermissions(user, sub, permissions); } private Permission getPermission(PermissionDTO dto) throws ObjectNotFoundException { @@ -1489,9 +1617,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long) - */ @Override public List getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException { List users = dao.getUsersSharingFoldersForUser(userId); @@ -1505,9 +1630,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return res; } - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long) - */ @Override public Set getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException { if (userId == null) @@ -1530,41 +1652,32 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return result; } - @Override - public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set permissions) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (fileId == null) - throw new ObjectNotFoundException("No folder specified"); - - User user = dao.getEntityById(User.class, userId); - FileHeader file = dao.getEntityById(FileHeader.class, fileId); - if(!file.hasModifyACLPermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); - - if (readForAll != null) - if (user.equals(file.getOwner())) - file.setReadForAll(readForAll); - else - throw new InsufficientPermissionsException("Only the owner can change the read-for-all flag"); - - // Update the file if there was a change. - if (readForAll != null || permissions != null && !permissions.isEmpty()) { - if (permissions != null && !permissions.isEmpty()) { - // Delete previous entries - for (Permission perm: file.getPermissions()) - dao.delete(perm); - file.getPermissions().clear(); - for (PermissionDTO dto : permissions) { - if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL())) - throw new InsufficientPermissionsException("Can't remove permissions from owner"); - // Don't include 'empty' permission - if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue; - file.addPermission(getPermission(dto)); - } + /** + * Set the provided permissions as the new permissions of the specified + * file. This method sets the modification date/user attributes to the + * current values as a side effect. + * + * @param file + * @param permissions + * @throws ObjectNotFoundException + * @throws InsufficientPermissionsException + */ + private void setFilePermissions(FileHeader file, + Set permissions) + throws ObjectNotFoundException, InsufficientPermissionsException { + if (permissions != null && !permissions.isEmpty()) { + // Delete previous entries. + for (Permission perm: file.getPermissions()) + dao.delete(perm); + file.getPermissions().clear(); + for (PermissionDTO dto : permissions) { + if (dto.getUser()!=null && dto.getUser().getId().equals(file.getOwner().getId()) && (!dto.hasRead() || !dto.hasWrite() || !dto.hasModifyACL())) + throw new InsufficientPermissionsException("Can't remove permissions from owner"); + // Don't include 'empty' permission. + if (!dto.getRead() && !dto.getWrite() && !dto.getModifyACL()) continue; + file.addPermission(getPermission(dto)); } - - dao.update(file); + dao.flush(); } } @@ -1795,7 +1908,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { * @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long) */ @Override - public void moveFiles(Long userId, List fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException { + public void moveFiles(Long userId, List fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException { for(Long l : fileIds){ FileHeader file = dao.getEntityById(FileHeader.class, l); moveFile(userId, l, destId, file.getName()); @@ -1827,6 +1940,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { for (final FileBody body : file.getBodies()) filesToRemove.add(body.getStoredFilePath()); dao.delete(file); + touchParentFolders(parent, user, new Date()); } //then remove physical files if everything is ok for(String physicalFileName : filesToRemove) @@ -1953,6 +2067,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { deleteActualFile(body.getStoredFilePath()); header.getBodies().remove(body); + Folder parent = header.getFolder(); + touchParentFolders(parent, user, new Date()); } @@ -2001,27 +2117,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } header.getCurrentBody().setVersion(1); - } - - /* (non-Javadoc) - * @see gr.ebs.gss.server.ejb.ExternalAPI#toggleFileVersioning(java.lang.Long, java.lang.Long, boolean) - */ - @Override - public void toggleFileVersioning(Long userId, Long fileId, boolean versioned) throws ObjectNotFoundException, InsufficientPermissionsException { - if (userId == null) - throw new ObjectNotFoundException("No user specified"); - if (fileId == null) - throw new ObjectNotFoundException("No file specified"); - User user = dao.getEntityById(User.class, userId); - FileHeader header = dao.getEntityById(FileHeader.class, fileId); - if(!header.hasWritePermission(user)) - throw new InsufficientPermissionsException("You don't have the necessary permissions"); - if(!header.isVersioned() == versioned){ - if(header.isVersioned()) - removeOldVersions(userId, fileId); - header.setVersioned(versioned); - - } + Folder parent = header.getFolder(); + touchParentFolders(parent, user, new Date()); } /** @@ -2235,6 +2332,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } catch (FileNotFoundException e) { throw new GSSIOException(e); } + touchParentFolders(parent, owner, new Date()); dao.flush(); indexFile(file.getId(), false); @@ -2273,6 +2371,8 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { } catch (FileNotFoundException e) { throw new GSSIOException(e); } + Folder parent = file.getFolder(); + touchParentFolders(parent, owner, new Date()); indexFile(fileId, false); return file.getDTO(); @@ -2286,7 +2386,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { */ private String identifyMimeType(String filename) { if (filename.indexOf('.') != -1) { - String extension = filename.substring(filename.lastIndexOf('.')); + String extension = filename.substring(filename.lastIndexOf('.')).toLowerCase(Locale.ENGLISH); if (".doc".equals(extension)) return "application/msword"; else if (".xls".equals(extension)) @@ -2295,6 +2395,16 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return "application/vnd.ms-powerpoint"; else if (".pdf".equals(extension)) return "application/pdf"; + else if (".gif".equals(extension)) + return "image/gif"; + else if (".jpg".equals(extension) || ".jpeg".equals(extension) || ".jpe".equals(extension)) + return "image/jpeg"; + else if (".tiff".equals(extension) || ".tif".equals(extension)) + return "image/tiff"; + else if (".png".equals(extension)) + return "image/png"; + else if (".bmp".equals(extension)) + return "image/bmp"; } // when all else fails assign the default mime type return DEFAULT_MIME_TYPE; @@ -2357,6 +2467,7 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { dao.flush(); header.addBody(body); + header.setAuditInfo(auditInfo); dao.create(body); } @@ -2513,13 +2624,6 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return true; } - /** - * Reset WebDAV password for given user. - * - * @param userId - * @return the new password - * @throws ObjectNotFoundException - */ @Override public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException { if (userId == null) @@ -2529,4 +2633,39 @@ public class ExternalAPIBean implements ExternalAPI, ExternalAPIRemote { return user.getWebDAVPassword(); } + @Override + public Invitation findInvite(String code) { + if (code == null) + return null; + return dao.findInvite(code); + } + + @Override + public void createLdapUser(String username, String firstname, String lastname, String email, String password) { + LDAPConnection lc = new LDAPConnection(); + LDAPAttributeSet attributeSet = new LDAPAttributeSet(); + attributeSet.add(new LDAPAttribute("objectClass", getConfiguration().getStringArray("objectClass"))); + attributeSet.add(new LDAPAttribute("uid", username)); + attributeSet.add(new LDAPAttribute("cn", new String[]{firstname + " " + lastname})); + attributeSet.add(new LDAPAttribute("sn", lastname)); + attributeSet.add(new LDAPAttribute("givenName", firstname)); + attributeSet.add(new LDAPAttribute("mail", email)); + attributeSet.add(new LDAPAttribute("userPassword", password)); + String dn = "uid=" + username + "," + getConfiguration().getString("baseDn"); + LDAPEntry newEntry = new LDAPEntry(dn, attributeSet); + try { + lc.connect(getConfiguration().getString("ldapHost"), LDAPConnection.DEFAULT_PORT); + lc.bind(LDAPConnection.LDAP_V3, getConfiguration().getString("bindDn"), + getConfiguration().getString("bindPassword").getBytes("UTF8")); + lc.add(newEntry); + logger.info("Successfully added LDAP account: " + dn); + lc.disconnect(); + } catch(LDAPException e) { + throw new RuntimeException(e); + } catch(UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + } + }