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;
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;
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;
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.
*
*/
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)
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");
}
@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)
" to write to this folder");
// Do the actual work.
- createFolder(name, parent, creator);
+ return createFolder(name, parent, creator);
}
/**
* @param name
* @param parent
* @param creator
- * @param owner
+ * @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) {
auditInfo.setModifiedBy(creator);
auditInfo.setModificationDate(now);
folder.setAuditInfo(auditInfo);
+ touchParentFolders(folder, auditInfo.getModifiedBy(), auditInfo.getModificationDate());
if (parent != null)
for (Permission p : parent.getPermissions()) {
folder.addPermission(permission);
}
dao.create(folder);
+ return folder.getDTO();
}
/*
- * (non-Javadoc)
+ * Deletes the given folder and all its subfolders and files
+ * Only the permissions for top folder are checked
*
* @see gr.ebs.gss.server.ejb.ExternalAPI#deleteFolder(java.lang.Long,
* java.lang.Long)
logger.info("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete folder " + folder.getName() + "(" + folder.getId() + ")");
}
+ removeSubfolderFiles(folder);
parent.removeSubfolder(folder);
dao.delete(folder);
+ touchParentFolders(parent, user, new Date());
+ }
+
+ /**
+ * Traverses the folder and deletes all actual files (file system)
+ * regardless of permissions
+ *
+ * @param folder
+ */
+ private void removeSubfolderFiles(Folder folder) {
+ //remove files for all subfolders
+ for (Folder subfolder:folder.getSubfolders())
+ removeSubfolderFiles(subfolder);
+ //remove this folder's file bodies (actual files)
+ for (FileHeader file:folder.getFiles()) {
+ for (FileBody body:file.getBodies())
+ deleteActualFile(body.getStoredFilePath());
+ indexFile(file.getId(), true);
+ }
}
@SuppressWarnings("unchecked")
}
@Override
- public void modifyFolder(Long userId, Long folderId, String folderName)
- throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException {
+ public FolderDTO updateFolder(Long userId, Long folderId, String folderName,
+ Set<PermissionDTO> 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);
+ // Do the actual modification.
+ folder.setName(folderName);
+ }
+ if (permissions != null)
+ setFolderPermissions(user, folder, permissions);
+
+ folder.getAuditInfo().setModificationDate(new Date());
+ folder.getAuditInfo().setModifiedBy(user);
dao.update(folder);
+ touchParentFolders(folder, user, new Date());
+ return folder.getDTO();
}
/*
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");
// Supply a more accurate problem description.
throw new GSSIOException("Problem creating file",ioe);
}
- return createFile(userId, folderId, name, mimeType, file);
+ return createFile(userId, folderId, name, mimeType, file.length(), file.getAbsolutePath());
}
/* (non-Javadoc)
final User user = dao.getEntityById(User.class, userId);
if (!file.hasDeletePermission(user))
throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
- for (final FileBody body : file.getBodies()) {
- final File fileContents = new File(body.getStoredFilePath());
- if (!fileContents.delete())
- logger.error("Could not delete file " + body.getStoredFilePath());
- }
+ for (final FileBody body : file.getBodies())
+ deleteActualFile(body.getStoredFilePath());
dao.delete(file);
+ touchParentFolders(parent, user, new Date());
indexFile(fileId, true);
}
- /*
- * (non-Javadoc)
- *
- * @see gr.ebs.gss.server.ejb.ExternalAPI#createTag(java.lang.Long,
- * java.lang.Long, java.lang.String)
- */
+ private void deleteActualFile(String filePath) {
+ if (filePath == null)
+ return;
+ File file = new File(filePath);
+ if (!file.delete())
+ logger.error("Could not delete file " + filePath);
+ }
+
public void createTag(final Long userId, final Long fileHeaderId, final String tag) throws ObjectNotFoundException {
if (userId == null)
throw new ObjectNotFoundException("No user specified");
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<String> 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<PermissionDTO> 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<FileTag> tags = file.getFileTags();
+ }
+
+ if (modificationDate != null)
+ file.getAuditInfo().setModificationDate(modificationDate);
+ else
+ file.getAuditInfo().setModificationDate(new Date());
+ file.getAuditInfo().setModifiedBy(user);
+ List<FileTag> tags = file.getFileTags();
if (tagSet != null) {
Iterator<FileTag> i = tags.iterator();
while (i.hasNext()) {
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)
// Supply a more accurate problem description.
throw new GSSIOException("Problem creating file",ioe);
}
- return updateFileContents(userId, fileId, mimeType, file);
+ return updateFileContents(userId, fileId, mimeType, file.length(), file.getAbsolutePath());
}
@Override
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;
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++) {
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)
}
@Override
- public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
+ public void moveFile(Long userId, Long fileId, Long destId, String destName) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
if (userId == null)
throw new ObjectNotFoundException("No user specified");
if (fileId == null)
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);
if (!file.hasDeletePermission(owner) || !destination.hasWritePermission(owner))
throw new InsufficientPermissionsException("User " + owner.getId() + " cannot move file " + file.getName() + "(" + file.getId() + ")");
- FileBody body = file.getCurrentBody();
- assert body != null;
- File contents = new File(body.getStoredFilePath());
- try {
- createFile(owner.getId(), destination.getId(), destName, body.getMimeType(), new FileInputStream(contents));
- } catch (FileNotFoundException e) {
- throw new ObjectNotFoundException("File contents not found for file " + body.getStoredFilePath());
- }
- deleteFile(userId, fileId);
+ // if the destination folder belongs to another user:
+ if (!file.getOwner().equals(destination.getOwner())) {
+ // (a) check if the destination quota allows the move
+ if(getQuotaLeft(destination.getOwner().getId()) < file.getTotalSize())
+ throw new QuotaExceededException("Not enough free space available");
+ User newOwner = destination.getOwner();
+ // (b) if quota OK, change the owner of the file
+ file.setOwner(newOwner);
+ // if the file has no permission for the new owner, add it
+ Permission ownerPermission = null;
+ for (final Permission p : file.getPermissions())
+ if (p.getUser() != null)
+ if (p.getUser().equals(newOwner)) {
+ ownerPermission = p;
+ break;
+ }
+ if (ownerPermission == null) {
+ ownerPermission = new Permission();
+ ownerPermission.setUser(newOwner);
+ file.addPermission(ownerPermission);
+ }
+ ownerPermission.setRead(true);
+ ownerPermission.setWrite(true);
+ ownerPermission.setModifyACL(true);
+ }
+ // 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)
}
@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<FileHeaderDTO> getDeletedFiles(Long userId) throws ObjectNotFoundException {
// Validate.
if (userId == null)
file.setDeleted(false);
dao.update(file);
+ touchParentFolders(parent, user, new Date());
}
@Override
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())
for (Folder subFolder : folder.getSubfolders())
removeFolderFromTrash(userId, subFolder.getId());
dao.update(folder);
+ touchParentFolders(folder, user, new Date());
}
@Override
}
@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)
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);
auditInfo.setModificationDate(now);
user.setAuditInfo(auditInfo);
user.generateAuthToken();
+ user.generateWebDAVPassword();
dao.create(user);
// Make sure we get an ID in the user object.
dao.flush();
}
@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;
}
- /* (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<PermissionDTO> 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<PermissionDTO> permissions) throws ObjectNotFoundException, InsufficientPermissionsException {
+ // Delete previous entries
+ for (Permission perm: folder.getPermissions())
+ dao.delete(perm);
folder.getPermissions().clear();
for (PermissionDTO dto : permissions) {
if (dto.getUser()!=null && dto.getUser().getId().equals(folder.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;
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 {
}
- /* (non-Javadoc)
- * @see gr.ebs.gss.server.ejb.ExternalAPI#getUsersSharingFoldersForUser(java.lang.Long)
- */
@Override
public List<UserDTO> getUsersSharingFoldersForUser(Long userId) throws ObjectNotFoundException {
List<User> users = dao.getUsersSharingFoldersForUser(userId);
return res;
}
- /* (non-Javadoc)
- * @see gr.ebs.gss.server.ejb.ExternalAPI#getFilePermissions(java.lang.Long, java.lang.Long)
- */
@Override
public Set<PermissionDTO> getFilePermissions(Long userId, Long fileId) throws ObjectNotFoundException, InsufficientPermissionsException {
if (userId == null)
return result;
}
- @Override
- public void setFilePermissions(Long userId, Long fileId, Boolean readForAll, Set<PermissionDTO> 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");
-
+ /**
+ * 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<PermissionDTO> 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.flush();
}
-
- // Update the file if there was a change.
- if (readForAll != null || permissions != null && !permissions.isEmpty())
- dao.update(file);
-
}
@Override
* @see gr.ebs.gss.server.ejb.ExternalAPI#moveFiles(java.lang.Long, java.util.List, java.lang.Long)
*/
@Override
- public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, DuplicateNameException, GSSIOException, QuotaExceededException {
+ public void moveFiles(Long userId, List<Long> fileIds, Long destId) throws InsufficientPermissionsException, ObjectNotFoundException, QuotaExceededException {
for(Long l : fileIds){
FileHeader file = dao.getEntityById(FileHeader.class, l);
moveFile(userId, l, destId, file.getName());
if (userId == null)
throw new ObjectNotFoundException("No user specified");
final User user = dao.getEntityById(User.class, userId);
- List<File> filesToRemove = new ArrayList<File>();
+ List<String> filesToRemove = new ArrayList<String>();
//first delete database objects
for(Long fileId : fileIds){
if (fileId == null)
throw new InsufficientPermissionsException("User " + user.getId() + " cannot delete file " + file.getName() + "(" + file.getId() + ")");
parent.removeFile(file);
- for (final FileBody body : file.getBodies()) {
- final File fileContents = new File(body.getStoredFilePath());
- filesToRemove.add(fileContents);
- }
+ 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(File physicalFile : filesToRemove)
- if (!physicalFile.delete())
- logger.error("Could not delete file " + physicalFile.getPath());
+ for(String physicalFileName : filesToRemove)
+ deleteActualFile(physicalFileName);
//then unindex deleted files
for(Long fileId : fileIds)
indexFile(fileId, true);
if(b.getVersion() == body.getVersion()-1)
header.setCurrentBody(b);
}
- final File fileContents = new File(body.getStoredFilePath());
- if (!fileContents.delete())
- logger.error("Could not delete file " + body.getStoredFilePath());
+ deleteActualFile(body.getStoredFilePath());
header.getBodies().remove(body);
+ Folder parent = header.getFolder();
+ touchParentFolders(parent, user, new Date());
}
while(it.hasNext()){
FileBody body = it.next();
if(!body.equals(header.getCurrentBody())){
- final File fileContents = new File(body.getStoredFilePath());
- if (!fileContents.delete())
- logger.error("Could not delete file " + body.getStoredFilePath());
+ deleteActualFile(body.getStoredFilePath());
it.remove();
dao.delete(body);
}
}
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());
}
/**
/**
* Gets the quota for specified userId
- * @param userId
- * @return
- */
- private Long getQuota(@SuppressWarnings("unused") Long userId){
- Long quota = getConfiguration().getLong("quota", new Long(52428800L));
- return quota;
- }
+ * @param userId
+ * @return
+ */
+ private Long getQuota(@SuppressWarnings("unused") Long userId){
+ Long quota = getConfiguration().getLong("quota", new Long(52428800L));
+ return quota;
+ }
public void rebuildSolrIndex() {
MessageProducer sender = null;
}
}
- public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, File fileObject)
+ public FileHeaderDTO createFile(Long userId, Long folderId, String name, String mimeType, long fileSize, String filePath)
throws DuplicateNameException, ObjectNotFoundException, GSSIOException,
InsufficientPermissionsException, QuotaExceededException {
// Validate.
// Create the file body.
try {
- createFileBody(name, contentType, fileObject, file, auditInfo, owner);
+ createFileBody(name, contentType, fileSize, filePath, file, auditInfo);
} catch (FileNotFoundException e) {
throw new GSSIOException(e);
}
+ touchParentFolders(parent, owner, new Date());
dao.flush();
indexFile(file.getId(), false);
/* (non-Javadoc)
* @see gr.ebs.gss.server.ejb.ExternalAPI#updateFileContents(java.lang.Long, java.lang.Long, java.lang.String, java.io.InputStream)
*/
- public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, File fileObject) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
+ public FileHeaderDTO updateFileContents(Long userId, Long fileId, String mimeType, long fileSize, String filePath) throws ObjectNotFoundException, GSSIOException, InsufficientPermissionsException, QuotaExceededException {
if (userId == null)
throw new ObjectNotFoundException("No user specified");
if (fileId == null)
auditInfo.setModifiedBy(owner);
auditInfo.setModificationDate(now);
try {
- createFileBody(file.getName(), contentType, fileObject, file, auditInfo, owner);
+ createFileBody(file.getName(), contentType, fileSize, filePath, file, auditInfo);
} catch (FileNotFoundException e) {
throw new GSSIOException(e);
}
+ Folder parent = file.getFolder();
+ touchParentFolders(parent, owner, new Date());
indexFile(fileId, false);
return file.getDTO();
*/
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))
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;
*
* @param name the original file name
* @param mimeType the content type
- * @param uploadedFile the uploaded file contents
+ * @param fileSize the uploaded file size
+ * @param filePath the uploaded file full path
* @param header the file header that will be associated with the new body
* @param auditInfo the audit info
* @param owner the owner of the file
* @throws FileNotFoundException
* @throws QuotaExceededException
*/
- private void createFileBody(String name, String mimeType, File uploadedFile,
- FileHeader header, AuditInfo auditInfo, User owner)
+ private void createFileBody(String name, String mimeType, long fileSize, String filePath,
+ FileHeader header, AuditInfo auditInfo)
throws FileNotFoundException, QuotaExceededException {
+
+ long currentTotalSize = 0;
+ if (!header.isVersioned() && header.getCurrentBody() != null && header.getBodies() != null)
+ currentTotalSize = header.getTotalSize();
+ Long quotaLeft = getQuotaLeft(header.getOwner().getId());
+ if(quotaLeft < fileSize-currentTotalSize) {
+ // quota exceeded -> delete the file
+ deleteActualFile(filePath);
+ throw new QuotaExceededException("Not enough free space available");
+ }
+
FileBody body = new FileBody();
// if no mime type or the generic mime type is defined by the client, then try to identify it from the filename extension
|| "octet/stream".equals(mimeType) || "application/unknown".equals(mimeType))
body.setMimeType(identifyMimeType(name));
else
- body.setMimeType(mimeType);
+ body.setMimeType(mimeType);
body.setAuditInfo(auditInfo);
- body.setFileSize(uploadedFile.length());
+ body.setFileSize(fileSize);
body.setOriginalFilename(name);
- body.setStoredFilePath(uploadedFile.getAbsolutePath());
+ body.setStoredFilePath(filePath);
//CLEAR OLD VERSION IF FILE IS NOT VERSIONED AND GETS UPDATED
if(!header.isVersioned() && header.getCurrentBody() != null){
header.setCurrentBody(null);
Iterator<FileBody> it = header.getBodies().iterator();
while(it.hasNext()){
FileBody bo = it.next();
- File fileContents = new File(bo.getStoredFilePath());
- if (!fileContents.delete())
- logger.error("Could not delete file " + bo.getStoredFilePath());
+ deleteActualFile(bo.getStoredFilePath());
it.remove();
dao.delete(bo);
}
}
}
- Long quotaLeft = getQuotaLeft(owner.getId());
- if(quotaLeft < uploadedFile.length())
- throw new QuotaExceededException("Not enough free space available");
dao.flush();
header.addBody(body);
+ header.setAuditInfo(auditInfo);
dao.create(body);
}
return true;
}
+ @Override
+ public String resetWebDAVPassword(Long userId) throws ObjectNotFoundException {
+ if (userId == null)
+ throw new ObjectNotFoundException("No user specified");
+ User user = dao.getEntityById(User.class, userId);
+ user.generateWebDAVPassword();
+ 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);
+ }
+
+ }
+
}