mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD (5.2) to 5.2.N (5.2.1)
126518 jkaabimofrad: Merged FILE-FOLDER-API (5.2.0) to HEAD (5.2) 122954 jvonka: (Quick) Shared Links API - add optional select/include of "allowableOperations" when authenticated and getting shared link info or find links (or even after create) RA-750, RA-777 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@126862 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -102,4 +102,6 @@ public interface QuickShareLinks
|
||||
* API Constants - query parameters, etc
|
||||
*/
|
||||
String PARAM_SHAREDBY = "sharedByUser";
|
||||
|
||||
String PARAM_SELECT_ISLINK = "allowableOperations";
|
||||
}
|
@@ -25,6 +25,7 @@ import org.alfresco.repo.quickshare.QuickShareServiceImpl.QuickShareEmailRequest
|
||||
import org.alfresco.repo.search.QueryParameterDefImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.site.SiteModel;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
@@ -67,6 +68,7 @@ import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
@@ -76,10 +78,13 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -114,6 +119,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
private SearchService searchService;
|
||||
private DictionaryService dictionaryService;
|
||||
private NamespaceService namespaceService;
|
||||
private SiteService siteService;
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry sr)
|
||||
{
|
||||
@@ -155,6 +161,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
this.searchService = sr.getSearchService();
|
||||
this.dictionaryService = sr.getDictionaryService();
|
||||
this.namespaceService = sr.getNamespaceService();
|
||||
this.siteService = sr.getSiteService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +169,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
* <p>
|
||||
* Note: does *not* require authenticated access for (public) shared link.
|
||||
*/
|
||||
public QuickShareLink readById(final String sharedId, Parameters parameters)
|
||||
public QuickShareLink readById(final String sharedId, final Parameters parameters)
|
||||
{
|
||||
checkEnabled();
|
||||
|
||||
@@ -177,7 +184,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
{
|
||||
public QuickShareLink doWork() throws Exception
|
||||
{
|
||||
return getQuickShareInfo(sharedId, noAuth);
|
||||
return getQuickShareInfo(sharedId, noAuth, parameters.getSelectedProperties());
|
||||
}
|
||||
}, networkTenantDomain);
|
||||
}
|
||||
@@ -264,14 +271,9 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
try
|
||||
{
|
||||
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)))
|
||||
String sharedByUserId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
if (! canDeleteSharedLink(nodeRef, sharedByUserId))
|
||||
{
|
||||
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
|
||||
}
|
||||
@@ -307,6 +309,8 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
|
||||
boolean noAuth = (AuthenticationUtil.getRunAsUser() == null);
|
||||
|
||||
List<String> selectParam = parameters.getSelectedProperties();
|
||||
|
||||
for (QuickShareLink qs : nodeIds)
|
||||
{
|
||||
String nodeId = qs.getNodeId();
|
||||
@@ -332,7 +336,7 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
try
|
||||
{
|
||||
QuickShareDTO qsDto = quickShareService.shareContent(nodeRef);
|
||||
result.add(getQuickShareInfo(qsDto.getId(), noAuth));
|
||||
result.add(getQuickShareInfo(qsDto.getId(), noAuth, selectParam));
|
||||
}
|
||||
catch (InvalidNodeRefException inre)
|
||||
{
|
||||
@@ -434,17 +438,18 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
sp.setSkipCount(pagingRequest.getSkipCount());
|
||||
sp.setMaxItems(pagingRequest.getMaxItems());
|
||||
|
||||
// TODO is perf ok with Solr 4 paging/sorting ? (otherwise make this optional via orderBy and leave default sort as undefined)
|
||||
sp.addSort("@" + ContentModel.PROP_MODIFIED, false);
|
||||
|
||||
ResultSet results = searchService.query(sp);
|
||||
|
||||
List<QuickShareLink> qsLinks = new ArrayList<>(results.length());
|
||||
|
||||
List<String> selectParam = parameters.getSelectedProperties();
|
||||
|
||||
for (ResultSetRow row : results)
|
||||
{
|
||||
NodeRef nodeRef = row.getNodeRef();
|
||||
qsLinks.add(getQuickShareInfo(nodeRef, false));
|
||||
qsLinks.add(getQuickShareInfo(nodeRef, false, selectParam));
|
||||
}
|
||||
|
||||
results.close();
|
||||
@@ -452,23 +457,23 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
return CollectionWithPagingInfo.asPaged(paging, qsLinks, results.hasMore(), new Long(results.getNumberFound()).intValue());
|
||||
}
|
||||
|
||||
private QuickShareLink getQuickShareInfo(String sharedId, boolean noAuth)
|
||||
private QuickShareLink getQuickShareInfo(String sharedId, boolean noAuth, List<String> selectParam)
|
||||
{
|
||||
checkValidShareId(sharedId);
|
||||
|
||||
Map<String, Object> map = (Map<String, Object>) quickShareService.getMetaData(sharedId).get("item");
|
||||
NodeRef nodeRef = new NodeRef((String) map.get("nodeRef"));
|
||||
|
||||
return getQuickShareInfo(nodeRef, map, noAuth);
|
||||
return getQuickShareInfo(nodeRef, map, noAuth, selectParam);
|
||||
}
|
||||
|
||||
private QuickShareLink getQuickShareInfo(NodeRef nodeRef, boolean noAuth)
|
||||
private QuickShareLink getQuickShareInfo(NodeRef nodeRef, boolean noAuth, List<String> selectParam)
|
||||
{
|
||||
Map<String, Object> map = (Map<String, Object>) quickShareService.getMetaData(nodeRef).get("item");
|
||||
return getQuickShareInfo(nodeRef, map , noAuth);
|
||||
return getQuickShareInfo(nodeRef, map , noAuth, selectParam);
|
||||
}
|
||||
|
||||
private QuickShareLink getQuickShareInfo(NodeRef nodeRef, Map<String, Object> map, boolean noAuth)
|
||||
private QuickShareLink getQuickShareInfo(NodeRef nodeRef, Map<String, Object> map, boolean noAuth, List<String> selectParam)
|
||||
{
|
||||
String sharedId = (String)map.get("sharedId");
|
||||
|
||||
@@ -489,17 +494,24 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
UserInfo modifiedByUser = Node.lookupUserInfo((String)nodeProps.get(ContentModel.PROP_MODIFIER), mapUserInfo, personService, displayNameOnly);
|
||||
|
||||
// TODO review - should we return sharedByUser for authenticated users only ?? (not exposed by V0 but needed for "find")
|
||||
UserInfo sharedByUser = Node.lookupUserInfo((String)nodeProps.get(QuickShareModel.PROP_QSHARE_SHAREDBY), mapUserInfo, personService, displayNameOnly);
|
||||
String sharedByUserId = (String)nodeProps.get(QuickShareModel.PROP_QSHARE_SHAREDBY);
|
||||
UserInfo sharedByUser = Node.lookupUserInfo(sharedByUserId, mapUserInfo, personService, displayNameOnly);
|
||||
|
||||
// TODO other "properties" (if needed) - eg. cm:title, cm:lastThumbnailModificationData, ... thumbnail info ...
|
||||
|
||||
QuickShareLink qs = new QuickShareLink(sharedId, nodeRef.getId());
|
||||
QuickShareLink qs = new QuickShareLink(sharedId, (noAuth ? null : nodeRef.getId()));
|
||||
qs.setName((String) map.get("name"));
|
||||
qs.setContent(contentInfo);
|
||||
qs.setModifiedAt((Date) map.get("modified"));
|
||||
qs.setModifiedByUser(modifiedByUser);
|
||||
qs.setSharedByUser(sharedByUser);
|
||||
|
||||
if ((! noAuth) && selectParam.contains(PARAM_SELECT_ISLINK))
|
||||
{
|
||||
if (canDeleteSharedLink(nodeRef, sharedByUserId))
|
||||
{
|
||||
qs.setAllowableOperations(Collections.singletonList("delete"));
|
||||
}
|
||||
}
|
||||
|
||||
return qs;
|
||||
}
|
||||
catch (InvalidSharedIdException ex)
|
||||
@@ -514,6 +526,54 @@ public class QuickShareLinksImpl implements QuickShareLinks, InitializingBean
|
||||
}
|
||||
}
|
||||
|
||||
// TODO push down to QuickShareService and also update v0 webscript (UnshareContentDelete)
|
||||
private boolean canDeleteSharedLink(NodeRef nodeRef, String sharedByUserId)
|
||||
{
|
||||
boolean canDeleteSharedLink = false;
|
||||
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
String siteName = getSiteName(nodeRef);
|
||||
|
||||
if (siteName != null)
|
||||
{
|
||||
// node belongs to a site - current user must be a manager or collaborator (irrespective of whether they shared the link or not)
|
||||
String role = siteService.getMembersRole(siteName, currentUser);
|
||||
if (role.equals(SiteModel.SITE_MANAGER) || role.equals(SiteModel.SITE_COLLABORATOR))
|
||||
{
|
||||
canDeleteSharedLink = true;
|
||||
}
|
||||
}
|
||||
else if ((currentUser.equals(sharedByUserId)) || (authorityService.isAdminAuthority(currentUser)))
|
||||
{
|
||||
// node does not belongs to a site - current user must be the person who shared the link or an admin
|
||||
canDeleteSharedLink = true;
|
||||
}
|
||||
|
||||
return canDeleteSharedLink;
|
||||
}
|
||||
|
||||
private String getSiteName(NodeRef nodeRef)
|
||||
{
|
||||
NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||
while (parent != null && !nodeService.getType(parent).equals(SiteModel.TYPE_SITE))
|
||||
{
|
||||
// check that we can read parent name
|
||||
String parentName = (String) nodeService.getProperty(parent, ContentModel.PROP_NAME);
|
||||
|
||||
if (nodeService.getPrimaryParent(nodeRef) != null)
|
||||
{
|
||||
parent = nodeService.getPrimaryParent(parent).getParentRef();
|
||||
}
|
||||
}
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return nodeService.getProperty(parent, ContentModel.PROP_NAME).toString();
|
||||
}
|
||||
|
||||
private void checkEnabled()
|
||||
{
|
||||
if (!enabled)
|
||||
|
@@ -19,6 +19,7 @@
|
||||
package org.alfresco.rest.api.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Representation of quick share link
|
||||
@@ -45,10 +46,13 @@ public class QuickShareLink
|
||||
private String name;
|
||||
private ContentInfo content;
|
||||
|
||||
protected Date modifiedAt;
|
||||
protected UserInfo modifiedByUser;
|
||||
private Date modifiedAt;
|
||||
private UserInfo modifiedByUser;
|
||||
|
||||
private UserInfo sharedByUser;
|
||||
|
||||
private List<String> allowableOperations;
|
||||
|
||||
protected UserInfo sharedByUser;
|
||||
|
||||
public QuickShareLink()
|
||||
{
|
||||
@@ -126,6 +130,16 @@ public class QuickShareLink
|
||||
this.sharedByUser = sharedByUser;
|
||||
}
|
||||
|
||||
public List<String> getAllowableOperations()
|
||||
{
|
||||
return allowableOperations;
|
||||
}
|
||||
|
||||
public void setAllowableOperations(List<String> allowableOperations)
|
||||
{
|
||||
this.allowableOperations = allowableOperations;
|
||||
}
|
||||
|
||||
// eg. for debug logging etc
|
||||
@Override
|
||||
public String toString()
|
||||
@@ -138,6 +152,7 @@ public class QuickShareLink
|
||||
sb.append(", modifiedByUser=").append(getModifiedByUser());
|
||||
sb.append(", sharedByUser=").append(getSharedByUser());
|
||||
sb.append(", content=").append(getContent());
|
||||
sb.append(", allowableOperations=").append(getAllowableOperations());
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@ package org.alfresco.rest.api.tests;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.People;
|
||||
import org.alfresco.rest.api.QuickShareLinks;
|
||||
import org.alfresco.rest.api.impl.QuickShareLinksImpl;
|
||||
@@ -41,6 +40,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -182,29 +182,54 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
|
||||
post(URL_SHARED_LINKS, user2, toJsonAsStringNonNull(body), 409);
|
||||
|
||||
|
||||
// auth access to get shared link info
|
||||
response = getSingle(QuickShareLinkEntityResource.class, user1, sharedId, null, 200);
|
||||
// auth access to get shared link info - as user1
|
||||
Map<String, String> params = Collections.singletonMap("select", "allowableOperations");
|
||||
response = getSingle(QuickShareLinkEntityResource.class, user1, sharedId, params, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
|
||||
assertEquals(sharedId, resp.getId());
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
assertEquals(docName1, resp.getName());
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
|
||||
assertEquals(user1, resp.getModifiedByUser().getId()); // returned if authenticated
|
||||
assertEquals(user2, resp.getSharedByUser().getId()); // returned if authenticated
|
||||
|
||||
assertNull(resp.getAllowableOperations());
|
||||
|
||||
// unauth access to get shared link info
|
||||
response = getSingle(QuickShareLinkEntityResource.class, null, sharedId, null, 200);
|
||||
// auth access to get shared link info - as user2
|
||||
params = Collections.singletonMap("select", "allowableOperations");
|
||||
response = getSingle(QuickShareLinkEntityResource.class, user2, sharedId, params, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
|
||||
assertEquals(sharedId, resp.getId());
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
assertEquals(docName1, resp.getName());
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
|
||||
assertNull(resp.getModifiedByUser().getId());
|
||||
assertEquals(user1, resp.getModifiedByUser().getId()); // returned if authenticated
|
||||
assertEquals(user2, resp.getSharedByUser().getId()); // returned if authenticated
|
||||
|
||||
assertEquals(1, resp.getAllowableOperations().size());
|
||||
assertEquals("delete", resp.getAllowableOperations().get(0));
|
||||
|
||||
// allowable operations not selected
|
||||
response = getSingle(QuickShareLinkEntityResource.class, user2, sharedId, null, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
assertNull(resp.getAllowableOperations());
|
||||
|
||||
|
||||
// unauth access to get shared link info
|
||||
params = Collections.singletonMap("select", "allowableOperations"); // note: this will be ignore for unauth access
|
||||
response = getSingle(QuickShareLinkEntityResource.class, null, sharedId, params, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
|
||||
assertEquals(sharedId, resp.getId());
|
||||
assertEquals(docName1, resp.getName());
|
||||
assertNull(resp.getNodeId()); // nodeId not returned
|
||||
assertNull(resp.getAllowableOperations()); // select is ignored
|
||||
|
||||
assertNull(resp.getModifiedByUser().getId()); // userId not returned
|
||||
assertEquals(user1+" "+user1, resp.getModifiedByUser().getDisplayName());
|
||||
assertNull(resp.getSharedByUser().getId());
|
||||
assertNull(resp.getSharedByUser().getId()); // userId not returned
|
||||
assertEquals(user2+" "+user2, resp.getSharedByUser().getDisplayName());
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user