ALF-1605/ALF-3452 - Share DocLib activities (check doc permission)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@23002 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2010-10-08 16:23:10 +00:00
parent 4ff69f599a
commit 01d9ad5384
5 changed files with 170 additions and 28 deletions

View File

@@ -82,6 +82,8 @@
<property name="siteService" ref="SiteService"/> <property name="siteService" ref="SiteService"/>
<property name="nodeService" ref="NodeService"/> <property name="nodeService" ref="NodeService"/>
<property name="contentService" ref="ContentService"/> <property name="contentService" ref="ContentService"/>
<property name="permissionService" ref="PermissionService"/>
<property name="templateSearchPaths"> <property name="templateSearchPaths">
<list> <list>
<value>alfresco/extension/templates/activities</value> <value>alfresco/extension/templates/activities</value>

View File

@@ -22,6 +22,7 @@ import java.sql.SQLException;
import java.util.Date; import java.util.Date;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.activities.post.lookup.PostLookup;
import org.alfresco.repo.domain.activities.ActivityPostDAO; import org.alfresco.repo.domain.activities.ActivityPostDAO;
import org.alfresco.repo.domain.activities.ActivityPostEntity; import org.alfresco.repo.domain.activities.ActivityPostEntity;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -29,9 +30,9 @@ import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.cmr.activities.ActivityPostService; import org.alfresco.service.cmr.activities.ActivityPostService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.ParameterCheck;
/** /**
* Activity Post Service Implementation * Activity Post Service Implementation
@@ -84,7 +85,7 @@ public class ActivityPostServiceImpl implements ActivityPostService
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append("}"); sb.append("{").append("\""+PostLookup.JSON_NODEREF_LOOKUP+"\":\"").append(nodeRef.toString()).append("\"").append("}");
postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING);
} }
@@ -97,7 +98,7 @@ public class ActivityPostServiceImpl implements ActivityPostService
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") sb.append("{").append("\""+PostLookup.JSON_NODEREF_LOOKUP+"\":\"").append(nodeRef.toString()).append("\"").append(",")
.append("\"name\":\"").append(name).append("\"") .append("\"name\":\"").append(name).append("\"")
.append("}"); .append("}");
@@ -116,10 +117,10 @@ public class ActivityPostServiceImpl implements ActivityPostService
ParameterCheck.mandatory("parentNodeRef", parentNodeRef); ParameterCheck.mandatory("parentNodeRef", parentNodeRef);
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("{").append("\"nodeRef\":\"").append(nodeRef.toString()).append("\"").append(",") sb.append("{").append("\""+PostLookup.JSON_NODEREF_LOOKUP+"\":\"").append(nodeRef.toString()).append("\"").append(",")
.append("\"name\":\"").append(name).append("\"").append(",") .append("\""+PostLookup.JSON_NAME+"\":\"").append(name).append("\"").append(",")
.append("\"typeQName\":\"").append(typeQName.toPrefixString()).append("\"").append(",") // TODO toPrefixString does not return prefix ??!! .append("\""+PostLookup.JSON_TYPEQNAME+"\":\"").append(typeQName.toPrefixString()).append("\"").append(",") // TODO toPrefixString does not return prefix ??!!
.append("\"parentNodeRef\":\"").append(parentNodeRef.toString()).append("\"") .append("\""+PostLookup.JSON_NODEREF_PARENT+"\":\"").append(parentNodeRef.toString()).append("\"")
.append("}"); .append("}");
postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING); postActivity(activityType, siteId, appTool, sb.toString(), ActivityPostEntity.STATUS.PENDING);

View File

@@ -257,7 +257,14 @@ public abstract class FeedTaskProcessor
excludedConnections++; excludedConnections++;
} }
else else
{ {
// read permission check
if (! canRead(ctx, connectedUser, model))
{
excludedConnections++;
continue;
}
for (String fmTemplate : fmTemplates) for (String fmTemplate : fmTemplates)
{ {
// determine format - based on template naming convention // determine format - based on template naming convention
@@ -448,6 +455,11 @@ public abstract class FeedTaskProcessor
return members; return members;
} }
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
{
throw new UnsupportedOperationException("FeedTaskProcessor: Remote callback for 'canRead' not implemented");
}
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
{ {
StringBuffer sbUrl = new StringBuffer(); StringBuffer sbUrl = new StringBuffer();

View File

@@ -28,6 +28,7 @@ import java.util.Set;
import org.alfresco.repo.activities.feed.FeedTaskProcessor; import org.alfresco.repo.activities.feed.FeedTaskProcessor;
import org.alfresco.repo.activities.feed.RepoCtx; import org.alfresco.repo.activities.feed.RepoCtx;
import org.alfresco.repo.activities.post.lookup.PostLookup;
import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedDAO;
import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.domain.activities.ActivityFeedEntity;
import org.alfresco.repo.domain.activities.ActivityPostDAO; import org.alfresco.repo.domain.activities.ActivityPostDAO;
@@ -37,7 +38,13 @@ import org.alfresco.repo.domain.activities.FeedControlEntity;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.template.ClassPathRepoTemplateLoader; import org.alfresco.repo.template.ClassPathRepoTemplateLoader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteService;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -68,6 +75,8 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
private SiteService siteService; private SiteService siteService;
private NodeService nodeService; private NodeService nodeService;
private ContentService contentService; private ContentService contentService;
private PermissionService permissionService;
private String defaultEncoding; private String defaultEncoding;
private List<String> templateSearchPaths; private List<String> templateSearchPaths;
private boolean useRemoteCallbacks; private boolean useRemoteCallbacks;
@@ -107,6 +116,11 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
this.contentService = contentService; this.contentService = contentService;
} }
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setDefaultEncoding(String defaultEncoding) public void setDefaultEncoding(String defaultEncoding)
{ {
this.defaultEncoding = defaultEncoding; this.defaultEncoding = defaultEncoding;
@@ -206,6 +220,105 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
} }
} }
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
{
if (useRemoteCallbacks)
{
// note: not implemented
return super.canRead(ctx, connectedUser, model);
}
else
{
if (permissionService == null)
{
// if permission service not configured then fallback (ie. no read permission check)
return true;
}
String nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF);
if (nodeRefStr == null)
{
nodeRefStr = (String)model.get(PostLookup.JSON_NODEREF_PARENT);
}
if (nodeRefStr != null)
{
final NodeRef nodeRef = new NodeRef(nodeRefStr);
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
{
public Boolean doWork() throws Exception
{
return canReadImpl(connectedUser, nodeRef);
}
}, AuthenticationUtil.getSystemUserName());
}
return true;
}
}
private boolean canReadImpl(final String connectedUser, final NodeRef nodeRef) throws Exception
{
// check for read permission
long start = System.currentTimeMillis();
try
{
// note: deleted node does not exist (hence no permission, although default permission check would return true which is problematic)
final NodeRef checkNodeRef;
if (nodeService.exists(nodeRef))
{
checkNodeRef = nodeRef;
}
else
{
// TODO: require ghosting - this is temp workaround (we should not rely on archive - may be permanently deleted, ie. not archived or already purged)
NodeRef archiveNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeRef.getId());
if (! nodeService.exists(archiveNodeRef))
{
return false;
}
checkNodeRef = archiveNodeRef;
}
if (connectedUser.equals(""))
{
// site feed (public site)
Set<AccessPermission> perms = permissionService.getAllSetPermissions(checkNodeRef);
for (AccessPermission perm : perms)
{
if (perm.getAuthority().equals(PermissionService.ALL_AUTHORITIES) &&
perm.getAuthorityType().equals(AuthorityType.EVERYONE) &&
perm.getPermission().equals(PermissionService.READ_PERMISSIONS) &&
perm.getAccessStatus().equals(AccessStatus.ALLOWED))
{
return true;
}
}
return false;
}
else
{
// user feed
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
{
public Boolean doWork() throws Exception
{
return (permissionService.hasPermission(checkNodeRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
}, connectedUser);
}
}
finally
{
if (logger.isDebugEnabled())
{
logger.debug("canRead: " + nodeRef + " in "+(System.currentTimeMillis()-start)+" msecs");
}
}
}
@Override @Override
protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception protected Map<String, List<String>> getActivityTypeTemplates(String repoEndPoint, String ticket, String subPath) throws Exception
{ {

View File

@@ -62,6 +62,20 @@ public class PostLookup
private PersonService personService; private PersonService personService;
private TenantService tenantService; private TenantService tenantService;
public static final String JSON_NODEREF_LOOKUP = "nodeRefL"; // requires additional lookup
public static final String JSON_NODEREF = "nodeRef";
public static final String JSON_NODEREF_PARENT = "parentNodeRef";
public static final String JSON_FIRSTNAME = "firstName";
public static final String JSON_LASTNAME = "lastName";
public static final String JSON_NAME = "name";
public static final String JSON_TYPEQNAME = "typeQName";
public static final String JSON_PARENT_NODEREF = "parentNodeRef";
public static final String JSON_DISPLAY_PATH = "displayPath";
public void setPostDAO(ActivityPostDAO postDAO) public void setPostDAO(ActivityPostDAO postDAO)
{ {
this.postDAO = postDAO; this.postDAO = postDAO;
@@ -139,9 +153,9 @@ public class PostLookup
String activityDataStr = null; String activityDataStr = null;
if (! jo.isNull("nodeRef")) if (! jo.isNull(JSON_NODEREF_LOOKUP))
{ {
String nodeRefStr = jo.getString("nodeRef"); String nodeRefStr = jo.getString(JSON_NODEREF_LOOKUP);
NodeRef nodeRef = new NodeRef(nodeRefStr); NodeRef nodeRef = new NodeRef(nodeRefStr);
// lookup additional node data // lookup additional node data
@@ -154,8 +168,8 @@ public class PostLookup
Pair<String, String> firstLastName = lookupPerson(postUserId); Pair<String, String> firstLastName = lookupPerson(postUserId);
if (firstLastName != null) if (firstLastName != null)
{ {
jo.put("firstName", firstLastName.getFirst()); jo.put(JSON_FIRSTNAME, firstLastName.getFirst());
jo.put("lastName", firstLastName.getSecond()); jo.put(JSON_LASTNAME, firstLastName.getSecond());
activityDataStr = jo.toString(); activityDataStr = jo.toString();
} }
@@ -283,22 +297,22 @@ public class PostLookup
public JSONObject execute() throws Throwable public JSONObject execute() throws Throwable
{ {
String name = ""; String name = "";
if (! jo.isNull("name")) if (! jo.isNull(JSON_NAME))
{ {
name = jo.getString("name"); name = jo.getString(JSON_NAME);
} }
NodeRef parentNodeRef = null; NodeRef parentNodeRef = null;
if (! jo.isNull("parentNodeRef")) if (! jo.isNull(JSON_PARENT_NODEREF))
{ {
parentNodeRef = new NodeRef(jo.getString("parentNodeRef")); parentNodeRef = new NodeRef(jo.getString(JSON_PARENT_NODEREF));
} }
String typeQName = ""; String typeQName = "";
if (! jo.isNull("typeQName")) if (! jo.isNull(JSON_TYPEQNAME))
{ {
typeQName = jo.getString("typeQName"); typeQName = jo.getString(JSON_TYPEQNAME);
} }
String displayPath = ""; String displayPath = "";
@@ -341,25 +355,25 @@ public class PostLookup
// parent node exists, lookup parent node path // parent node exists, lookup parent node path
path = nodeService.getPath(parentNodeRef); path = nodeService.getPath(parentNodeRef);
} }
if (path != null) if (path != null)
{ {
// lookup display path // lookup display path
displayPath = path.toDisplayPath(nodeService, permissionService); displayPath = path.toDisplayPath(nodeService, permissionService);
// note: for now, also tack on the node name // note: for now, also tack on the node name
displayPath += "/" + name; displayPath += "/" + name;
} }
// merge with existing activity data // merge with existing activity data
jo.put("name", name); jo.put(JSON_NAME, name);
jo.put("nodeRef", nodeRef.toString()); jo.put(JSON_NODEREF, nodeRef.toString());
jo.put("typeQName", typeQName); jo.put(JSON_TYPEQNAME, typeQName);
jo.put("parentNodeRef", (parentNodeRef != null ? parentNodeRef.toString() : null)); jo.put(JSON_PARENT_NODEREF, (parentNodeRef != null ? parentNodeRef.toString() : null));
jo.put("displayPath", displayPath); jo.put(JSON_DISPLAY_PATH, displayPath);
jo.put("firstName", firstName); jo.put(JSON_FIRSTNAME, firstName);
jo.put("lastName", lastName); jo.put(JSON_LASTNAME, lastName);
return jo; return jo;
} }
}; };