diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index 229420494d..5a543416e3 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -486,6 +486,8 @@
+
+
diff --git a/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java b/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java
index e2ee7da22f..50b9db2a10 100644
--- a/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java
+++ b/source/java/org/alfresco/rest/api/impl/QuickShareLinksImpl.java
@@ -19,6 +19,8 @@
package org.alfresco.rest.api.impl;
import org.alfresco.model.QuickShareModel;
+import org.alfresco.repo.security.authentication.AuthenticationUtil;
+import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.QuickShareLinks;
@@ -26,6 +28,8 @@ import org.alfresco.rest.api.model.ContentInfo;
import org.alfresco.rest.api.model.QuickShareLink;
import org.alfresco.rest.api.model.UserInfo;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
+import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
+import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.Parameters;
@@ -36,6 +40,8 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.cmr.security.AuthorityService;
+import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
@@ -50,6 +56,8 @@ import java.util.Map;
/**
* Centralises access to quick share services and maps between representations.
*
+ * TODO - if QuickShare is disabled should we return 403 (as below) or 404 (eg. when accessing a link) ?
+ *
* @author janv
*
* @since publicapi1.0
@@ -64,6 +72,8 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
private QuickShareService quickShareService;
private Nodes nodes;
private NodeService nodeService;
+ private PersonService personService;
+ private AuthorityService authorityService;
public void setQuickShareService(QuickShareService quickShareService)
{
@@ -80,6 +90,16 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
this.nodeService = nodeService;
}
+ public void setPersonService(PersonService personService)
+ {
+ this.personService = personService;
+ }
+
+ public void setAuthorityService(AuthorityService authorityService)
+ {
+ this.authorityService = authorityService;
+ }
+
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
@@ -91,26 +111,25 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
ParameterCheck.mandatory("quickShareService", this.quickShareService);
ParameterCheck.mandatory("nodes", this.nodes);
ParameterCheck.mandatory("nodeService", this.nodeService);
+ ParameterCheck.mandatory("personService", this.personService);
+ ParameterCheck.mandatory("authorityService", this.authorityService);
}
/**
* Returns limited metadata regarding the shared (content) link.
- *
+ *
* Note: does *not* require authenticated access for (public) shared link.
*/
public QuickShareLink readById(String sharedId, Parameters parameters)
{
- if (! enabled)
- {
- throw new PermissionDeniedException(DISABLED);
- }
+ checkEnabled();
return getQuickShareInfo(sharedId);
}
/**
* Download content via shared link.
- *
+ *
* Note: does *not* require authenticated access for (public) shared link.
*
* @param sharedId
@@ -120,10 +139,8 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
*/
public BinaryResource readProperty(String sharedId, final Parameters parameters) throws EntityNotFoundException
{
- if (! enabled)
- {
- throw new PermissionDeniedException(DISABLED);
- }
+ checkEnabled();
+ checkValidShareId(sharedId);
try
{
@@ -137,7 +154,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
public BinaryResource doWork() throws Exception
{
// belt-and-braces (similar to QuickShareContentGet)
- if (! nodeService.hasAspect(nodeRef, QuickShareModel.ASPECT_QSHARE))
+ if (!nodeService.hasAspect(nodeRef, QuickShareModel.ASPECT_QSHARE))
{
throw new InvalidNodeRefException(nodeRef);
}
@@ -148,30 +165,42 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
}
catch (InvalidSharedIdException ex)
{
- logger.warn("Unable to find: "+sharedId);
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ logger.warn("Unable to find: " + sharedId);
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
}
- catch (InvalidNodeRefException inre){
- logger.warn("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ catch (InvalidNodeRefException inre)
+ {
+ logger.warn("Unable to find: " + sharedId + " [" + inre.getNodeRef() + "]");
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
}
}
/**
* Delete the shared link.
- *
+ *
* Once deleted, the shared link will no longer exist hence get/download will no longer work (ie. return 404).
* If the link is later re-created then a new unique shared id will be generated.
- *
+ *
* Requires authenticated access.
*
* @param sharedId String id of the quick share
*/
public void delete(String sharedId, Parameters parameters)
{
- if (! enabled)
+ checkEnabled();
+ checkValidShareId(sharedId);
+
+ NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
+ String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
+
+ // TODO site check - see ACE-XXX
+ //String siteName = getSiteName(nodeRef);
+
+ String sharedBy = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
+
+ if ((!currentUser.equals(sharedBy)) && (!authorityService.isAdminAuthority(currentUser)))
{
- throw new PermissionDeniedException(DISABLED);
+ throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
}
try
@@ -180,18 +209,19 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
}
catch (InvalidSharedIdException ex)
{
- logger.warn("Unable to find: "+sharedId);
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ logger.warn("Unable to find: " + sharedId);
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
}
- catch (InvalidNodeRefException inre){
- logger.warn("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ catch (InvalidNodeRefException inre)
+ {
+ logger.warn("Unable to find: " + sharedId + " [" + inre.getNodeRef() + "]");
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
}
}
/**
* Create quick share.
- *
+ *
* Requires authenticated access.
*
* @param nodeIds
@@ -200,15 +230,37 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
*/
public List create(List nodeIds, Parameters parameters)
{
+ checkEnabled();
+
List result = new ArrayList<>(nodeIds.size());
for (QuickShareLink qs : nodeIds)
{
String nodeId = qs.getNodeId();
- QuickShareDTO qsDto = quickShareService.shareContent(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId));
- // TODO should we skip errors (eg. broken share) ?
- result.add(getQuickShareInfo(qsDto.getId()));
+ if (nodeId == null)
+ {
+ throw new InvalidArgumentException("A valid nodeId must be specified !");
+ }
+
+ NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
+
+ try
+ {
+ // Note: this throws AccessDeniedException (=> 403) via QuickShareService (when NodeService tries to getAspects)
+ QuickShareDTO qsDto = quickShareService.shareContent(nodeRef);
+ result.add(getQuickShareInfo(qsDto.getId()));
+ }
+ catch (AccessDeniedException ade)
+ {
+ logger.warn("Unable to create shared link: [" + nodeRef + "]");
+ throw new PermissionDeniedException("Unable to create shared link: " + nodeId);
+ }
+ catch (InvalidNodeRefException inre)
+ {
+ logger.warn("Unable to create shared link: [" + nodeRef + "]");
+ throw new EntityNotFoundException("Unable to create shared link: " + nodeId);
+ }
}
return result;
@@ -216,35 +268,70 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
private QuickShareLink getQuickShareInfo(String sharedId)
{
+ checkValidShareId(sharedId);
+
try
{
- Map map = (Map)quickShareService.getMetaData(sharedId).get("item");
+ Map map = (Map) quickShareService.getMetaData(sharedId).get("item");
- String nodeId = new NodeRef((String)map.get("nodeRef")).getId();
+ NodeRef nodeRef = new NodeRef((String) map.get("nodeRef"));
- ContentInfo contentInfo = new ContentInfo((String)map.get("mimetype"), null, (Long)map.get("size"), null);
+ ContentInfo contentInfo = new ContentInfo((String) map.get("mimetype"), null, (Long) map.get("size"), null);
- // note: we do not return modifier user id (to be consistent with v0 internal - limited disclosure)
- UserInfo modifier = new UserInfo(null,(String)map.get("modifierFirstName"), (String)map.get("modifierLastName"));
+ // note: we do not currently return userids (to be consistent with v0 internal - limited disclosure)
+ UserInfo modifiedByUser = new UserInfo(null, (String) map.get("modifierFirstName"), (String) map.get("modifierLastName"));
+ // TODO review - limit to authenticated users ? (not exposed by V0 but needed for "find")
+ UserInfo sharedByUser = null;
+ String sharedByUserId = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
+ if (sharedByUserId != null)
+ {
+ NodeRef pRef = personService.getPerson(sharedByUserId);
+ if (pRef != null)
+ {
+ PersonService.PersonInfo pInfo = personService.getPerson(pRef);
+ if (pInfo != null)
+ {
+ sharedByUser = new UserInfo(null, pInfo.getFirstName(), pInfo.getLastName());
+ }
+ }
+ }
// TODO other "properties" (if needed) - eg. cm:title, cm:lastThumbnailModificationData, ... thumbnail info ...
- QuickShareLink qs = new QuickShareLink(sharedId, nodeId);
- qs.setName((String)map.get("name"));
+ QuickShareLink qs = new QuickShareLink(sharedId, nodeRef.getId());
+ qs.setName((String) map.get("name"));
qs.setContent(contentInfo);
- qs.setModifiedAt((Date)map.get("modified"));
- qs.setModifiedByUser(modifier);
+ qs.setModifiedAt((Date) map.get("modified"));
+ qs.setModifiedByUser(modifiedByUser);
+ qs.setSharedByUser(sharedByUser);
return qs;
}
catch (InvalidSharedIdException ex)
{
- logger.warn("Unable to find: "+sharedId);
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ logger.warn("Unable to find: " + sharedId);
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
}
- catch (InvalidNodeRefException inre){
- logger.warn("Unable to find: "+sharedId+" ["+inre.getNodeRef()+"]");
- throw new EntityNotFoundException("Unable to find: "+sharedId);
+ catch (InvalidNodeRefException inre)
+ {
+ logger.warn("Unable to find: " + sharedId + " [" + inre.getNodeRef() + "]");
+ throw new EntityNotFoundException("Unable to find: " + sharedId);
+ }
+ }
+
+ private void checkEnabled()
+ {
+ if (!enabled)
+ {
+ throw new NotFoundException(DISABLED);
+ }
+ }
+
+ private void checkValidShareId(String sharedId)
+ {
+ if (sharedId==null)
+ {
+ throw new InvalidArgumentException("A valid sharedId must be specified !");
}
}
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/rest/api/model/QuickShareLink.java b/source/java/org/alfresco/rest/api/model/QuickShareLink.java
index 6f2b52b632..95d84cf4b2 100644
--- a/source/java/org/alfresco/rest/api/model/QuickShareLink.java
+++ b/source/java/org/alfresco/rest/api/model/QuickShareLink.java
@@ -46,6 +46,8 @@ public class QuickShareLink
protected Date modifiedAt;
protected UserInfo modifiedByUser;
+ protected UserInfo sharedByUser;
+
public QuickShareLink()
{
}
@@ -112,6 +114,16 @@ public class QuickShareLink
this.modifiedByUser = modifiedByUser;
}
+ public UserInfo getSharedByUser()
+ {
+ return sharedByUser;
+ }
+
+ public void setSharedByUser(UserInfo sharedByUser)
+ {
+ this.sharedByUser = sharedByUser;
+ }
+
// eg. for debug logging etc
@Override
public String toString()
@@ -122,6 +134,7 @@ public class QuickShareLink
sb.append(", name=").append(getName());
sb.append(", modifiedAt=").append(getModifiedAt());
sb.append(", modifiedByUser=").append(getModifiedByUser());
+ sb.append(", sharedByUser=").append(getSharedByUser());
sb.append(", content=").append(getContent());
sb.append("]");
return sb.toString();