Skip to content

Commit

Permalink
SAK-32149 elfinder allow upload when you can’t modify (sakaiproject#4470
Browse files Browse the repository at this point in the history
)

If you have permission to create new files in a folder but you can’t modify the actual folder then we shouldn’t say that you don’t have write access as elfinder then doesn’t allow you to upload a file.

However if you can’t change a folder and you attempt to rename it you will then get an error, but with the permission model that elfinder currently has this is the best we can do.
  • Loading branch information
buckett authored and jonespm committed Jun 13, 2017
1 parent 730eeba commit d9548df
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import cn.bluejoe.elfinder.controller.ErrorException;
import cn.bluejoe.elfinder.service.FsItem;
import org.sakaiproject.authz.api.SecurityAdvisor;
import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.thread_local.api.ThreadLocalManager;
import org.sakaiproject.user.api.UserDirectoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sakaiproject.content.api.*;
Expand Down Expand Up @@ -33,6 +37,9 @@ public class ContentSiteVolumeFactory implements SiteVolumeFactory {

protected ContentHostingService contentHostingService;
protected SiteService siteService;
protected SecurityService securityService;
protected UserDirectoryService userDirectoryService;
protected ThreadLocalManager threadLocalManager;

public void setContentHostingService(ContentHostingService contentHostingService) {
this.contentHostingService = contentHostingService;
Expand All @@ -42,6 +49,22 @@ public void setSiteService(SiteService siteService) {
this.siteService = siteService;
}

public SecurityService getSecurityService() {
return securityService;
}

public void setSecurityService(SecurityService securityService) {
this.securityService = securityService;
}

public void setUserDirectoryService(UserDirectoryService userDirectoryService) {
this.userDirectoryService = userDirectoryService;
}

public void setThreadLocalManager(ThreadLocalManager threadLocalManager) {
this.threadLocalManager = threadLocalManager;
}

@Override
public String getPrefix() {
return "content";
Expand Down Expand Up @@ -80,7 +103,10 @@ public SiteVolumeFactory getSiteVolumeFactory() {
public boolean isWriteable(FsItem item) {
String id = asId(item);
if (contentHostingService.isCollection(id)) {
return contentHostingService.allowUpdateCollection(id);
// Sakai has more fine grain permissions that elfinder so we allow on either of these and then
// if the end user can't perform one of the actions later on if will fail.
return contentHostingService.allowAddResource(id + "dummy") ||
contentHostingService.allowUpdateCollection(id);
} else {
return contentHostingService.allowUpdateResource(id);
}
Expand Down Expand Up @@ -109,7 +135,20 @@ public void createFile(FsItem fsi) throws IOException {
contentHostingService.commitResource(cre, org.sakaiproject.event.api.NotificationService.NOTI_NONE);
//update saved ID incase it wasn't the same
((ContentFsItem) fsi).setId(cre.getId());

// This is because the user might not have permission to update the file and elfinder does the upload
// in 2 steps. This will get removed at the end of the request.
SecurityAdvisor advisor = (userId, function, reference) -> {
// Check userId so event publication doesn't get confused
if (userDirectoryService.getCurrentUser().getId().equals(userId) &&
reference.equals(cre.getReference()) && function.startsWith("content.")) {
return SecurityAdvisor.SecurityAdvice.ALLOWED;
}
return SecurityAdvisor.SecurityAdvice.PASS;
};
securityService.pushAdvisor(advisor);
// We put this on a thead local so we can correctly remove it in the write stream if we get called.
// Otherwise it will get removed when the request ends.
threadLocalManager.set(getClass().getName()+":advisor", advisor);
} catch (SakaiException se) {
throw new IOException("Failed to create new file: " + id, se);
}
Expand Down Expand Up @@ -394,6 +433,10 @@ public void writeStream(final FsItem fsi, InputStream is) throws IOException {
ContentResourceEdit resource = contentHostingService.editResource(id);
resource.setContent(is);
contentHostingService.commitResource(resource, org.sakaiproject.event.api.NotificationService.NOTI_NONE);
Object advisor = threadLocalManager.get(getClass().getName()+":advisor");
if (advisor instanceof SecurityAdvisor) {
securityService.popAdvisor((SecurityAdvisor) advisor);
}
} catch (SakaiException se) {
throw new IOException("Failed to open input stream for: " + id, se);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@
<bean class="org.sakaiproject.elfinder.sakai.content.ContentSiteVolumeFactory">
<property name="contentHostingService" ref="org.sakaiproject.content.api.ContentHostingService"/>
<property name="siteService" ref="org.sakaiproject.site.api.SiteService"/>
</bean>
<property name="securityService" ref="org.sakaiproject.authz.api.SecurityService"/>
<property name="userDirectoryService" ref="org.sakaiproject.user.api.UserDirectoryService"/>
<property name="threadLocalManager" ref="org.sakaiproject.thread_local.api.ThreadLocalManager"/>
</bean>
<bean class="org.sakaiproject.elfinder.sakai.content.DropboxSiteVolumeFactory">
<property name="contentHostingService" ref="org.sakaiproject.content.api.ContentHostingService"/>
<property name="siteService" ref="org.sakaiproject.site.api.SiteService"/>
<property name="contentHostingService" ref="org.sakaiproject.content.api.ContentHostingService"/>
<property name="siteService" ref="org.sakaiproject.site.api.SiteService"/>
<property name="securityService" ref="org.sakaiproject.authz.api.SecurityService"/>
<property name="userDirectoryService" ref="org.sakaiproject.user.api.UserDirectoryService"/>
<property name="threadLocalManager" ref="org.sakaiproject.thread_local.api.ThreadLocalManager"/>
</bean>
<bean class="org.sakaiproject.elfinder.sakai.msgcntr.MsgCntrSiteVolumeFactory">
<property name="discussionForumManager" ref="org.sakaiproject.api.app.messageforums.ui.DiscussionForumManager"/>
Expand Down

0 comments on commit d9548df

Please sign in to comment.