mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged DEV to HEAD:
32658: THOR-775: Fix activities (followers + private sites) 32670: THOR-775: Privacy: Some private activities are shown when user A is following user B (eg. commented on) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32708 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -47,6 +47,7 @@ import org.alfresco.repo.template.ISO8601DateFormatMethod;
|
|||||||
import org.alfresco.repo.tenant.TenantService;
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.util.JSONtoFmModel;
|
import org.alfresco.util.JSONtoFmModel;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
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.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@@ -119,9 +120,11 @@ public abstract class FeedTaskProcessor
|
|||||||
|
|
||||||
Configuration cfg = getFreemarkerConfiguration(ctx);
|
Configuration cfg = getFreemarkerConfiguration(ctx);
|
||||||
|
|
||||||
|
// local caches for this run of activity posts
|
||||||
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
Map<String, List<String>> activityTemplates = new HashMap<String, List<String>>(10);
|
||||||
Map<String, Set<String>> siteConnectedUsers = new TreeMap<String, Set<String>>();
|
Map<String, Set<String>> siteConnectedUsers = new HashMap<String, Set<String>>(); // site -> site members
|
||||||
Map<String, Set<String>> followers = new TreeMap<String, Set<String>>();
|
Map<Pair<String, String>, Set<String>> followerConnectedUsers = new HashMap<Pair<String, String>, Set<String>>(); // user -> followers
|
||||||
|
Map<Pair<String, String>, Boolean> canUserReadSite = new HashMap<Pair<String, String>, Boolean>(); // <user, site> -> true/false (note: used when following, implied as true for site members)
|
||||||
Map<String, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
|
Map<String, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
|
||||||
Map<String, Template> templateCache = new TreeMap<String, Template>();
|
Map<String, Template> templateCache = new TreeMap<String, Template>();
|
||||||
|
|
||||||
@@ -258,60 +261,18 @@ public abstract class FeedTaskProcessor
|
|||||||
model.put("xmldate", new ISO8601DateFormatMethod());
|
model.put("xmldate", new ISO8601DateFormatMethod());
|
||||||
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
model.put("repoEndPoint", ctx.getRepoEndPoint());
|
||||||
|
|
||||||
// Recipients of this post
|
// Get recipients of this post
|
||||||
Set<String> recipients = new HashSet<String>();
|
Set<String> recipients = null;
|
||||||
|
try
|
||||||
// Add site members to recipient list
|
|
||||||
if (thisSite.length() > 0)
|
|
||||||
{
|
|
||||||
// Get the members of this site - save hammering the repository by reusing cached site members
|
|
||||||
Set<String> connectedUsers = siteConnectedUsers.get(thisSite);
|
|
||||||
if (connectedUsers == null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Repository callback to get site members
|
|
||||||
connectedUsers = getSiteMembers(ctx, thisSite, tenantDomain);
|
|
||||||
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get site members: " + e);
|
|
||||||
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache them for future use in this same invocation
|
|
||||||
siteConnectedUsers.put(thisSite, connectedUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
recipients.addAll(connectedUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add followers to recipient list
|
|
||||||
|
|
||||||
// MT Share - mangle key to be within context of tenant
|
|
||||||
String key = getTenantKey(activityPost.getUserId(), tenantDomain);
|
|
||||||
Set<String> followerUsers = followers.get(key);
|
|
||||||
if (followerUsers == null)
|
|
||||||
{
|
{
|
||||||
try
|
recipients = getRecipients(ctx, thisSite, activityPost.getUserId(), tenantDomain, siteConnectedUsers, followerConnectedUsers, canUserReadSite);
|
||||||
{
|
}
|
||||||
followerUsers = getFollowers(activityPost.getUserId(), tenantDomain);
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
catch(Exception e)
|
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get recipients: " + e);
|
||||||
{
|
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
||||||
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get followers: " + e);
|
continue;
|
||||||
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
followers.put(key, followerUsers);
|
|
||||||
}
|
}
|
||||||
recipients.addAll(followerUsers);
|
|
||||||
|
|
||||||
// Add the originator to recipients
|
|
||||||
recipients.add(activityPost.getUserId());
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -345,7 +306,7 @@ public abstract class FeedTaskProcessor
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// read permission check
|
// node read permission check (if nodeRef is present)
|
||||||
if (! canRead(ctx, recipient, model))
|
if (! canRead(ctx, recipient, model))
|
||||||
{
|
{
|
||||||
excludedConnections++;
|
excludedConnections++;
|
||||||
@@ -449,7 +410,89 @@ public abstract class FeedTaskProcessor
|
|||||||
logger.info(sb.toString());
|
logger.info(sb.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<String> getRecipients(RepoCtx ctx, String siteId, String postUserId, String tenantDomain,
|
||||||
|
Map<String, Set<String>> siteConnectedUsers, Map<Pair<String, String>, Set<String>> followerConnectedUsers, Map<Pair<String, String>, Boolean> canUserReadSite) throws Exception
|
||||||
|
{
|
||||||
|
// Recipients of this post
|
||||||
|
Set<String> recipients = new HashSet<String>();
|
||||||
|
|
||||||
|
// Add site members to recipient list
|
||||||
|
if (siteId.length() > 0)
|
||||||
|
{
|
||||||
|
// Get the members of this site - save hammering the repository by reusing cached site members
|
||||||
|
Set<String> connectedUsers = siteConnectedUsers.get(siteId);
|
||||||
|
if (connectedUsers == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Repository callback to get site members
|
||||||
|
connectedUsers = getSiteMembers(ctx, siteId, tenantDomain);
|
||||||
|
connectedUsers.add(""); // add empty posting userid - to represent site feed !
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to get site members: "+e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache them for future use (across activity posts handled) by this same invocation
|
||||||
|
siteConnectedUsers.put(siteId, connectedUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
recipients.addAll(connectedUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add followers to recipient list
|
||||||
|
|
||||||
|
// MT Share
|
||||||
|
Pair<String, String> userTenantKey = new Pair<String, String>(postUserId, tenantDomain);
|
||||||
|
Set<String> followerUsers = followerConnectedUsers.get(userTenantKey);
|
||||||
|
if (followerUsers == null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
followerUsers = getFollowers(postUserId, tenantDomain);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to get followers: "+e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache them for future use (across activity posts handled) by this same invocation
|
||||||
|
followerConnectedUsers.put(userTenantKey, followerUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteId.length() > 0)
|
||||||
|
{
|
||||||
|
for (String followerUser : followerUsers)
|
||||||
|
{
|
||||||
|
Pair<String, String> userSiteKey = new Pair<String, String>(followerUser, siteId);
|
||||||
|
Boolean canRead = canUserReadSite.get(userSiteKey);
|
||||||
|
if (canRead == null)
|
||||||
|
{
|
||||||
|
// site read permission check (note: only check followers since implied for site members)
|
||||||
|
canRead = canReadSite(ctx, siteId, followerUser, tenantDomain);
|
||||||
|
canUserReadSite.put(userSiteKey, canRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canRead)
|
||||||
|
{
|
||||||
|
recipients.add(followerUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
recipients.addAll(followerUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add the originator to recipients
|
||||||
|
recipients.add(postUserId);
|
||||||
|
|
||||||
|
return recipients;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void startTransaction() throws SQLException;
|
public abstract void startTransaction() throws SQLException;
|
||||||
|
|
||||||
public abstract void commitTransaction() throws SQLException;
|
public abstract void commitTransaction() throws SQLException;
|
||||||
@@ -530,11 +573,6 @@ public abstract class FeedTaskProcessor
|
|||||||
return TenantService.DEFAULT_DOMAIN;
|
return TenantService.DEFAULT_DOMAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getTenantKey(String name, String tenantDomain)
|
|
||||||
{
|
|
||||||
return tenantDomain + "." + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Set<String> getSiteMembers(RepoCtx ctx, String siteId, String tenantDomain) throws Exception
|
protected Set<String> getSiteMembers(RepoCtx ctx, String siteId, String tenantDomain) throws Exception
|
||||||
{
|
{
|
||||||
// note: tenant domain ignored her - it should already be part of the siteId
|
// note: tenant domain ignored her - it should already be part of the siteId
|
||||||
@@ -567,14 +605,10 @@ public abstract class FeedTaskProcessor
|
|||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected abstract Set<String> getFollowers(String userId, String tenantDomain) throws Exception;
|
protected abstract Set<String> getFollowers(String userId, String tenantDomain) throws Exception;
|
||||||
|
protected abstract boolean canReadSite(final RepoCtx ctx, String siteIdIn, String connectedUser, final String tenantDomain) throws Exception;
|
||||||
|
protected abstract boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception;
|
||||||
|
|
||||||
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();
|
||||||
|
@@ -267,49 +267,70 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain));
|
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean canReadSite(final RepoCtx ctx, String siteIdIn, String connectedUser, final String tenantDomain) throws Exception
|
||||||
|
{
|
||||||
|
if (useRemoteCallbacks)
|
||||||
|
{
|
||||||
|
// note: not implemented
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String siteId = tenantService.getBaseName(siteIdIn, true);
|
||||||
|
|
||||||
|
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
||||||
|
{
|
||||||
|
public Boolean doWork() throws Exception
|
||||||
|
{
|
||||||
|
return (siteService.getSite(siteId) != null);
|
||||||
|
}
|
||||||
|
}, connectedUser);
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
protected boolean canRead(RepoCtx ctx, final String connectedUser, Map<String, Object> model) throws Exception
|
||||||
{
|
{
|
||||||
if (useRemoteCallbacks)
|
if (useRemoteCallbacks)
|
||||||
{
|
{
|
||||||
// note: not implemented
|
// note: not implemented
|
||||||
return super.canRead(ctx, connectedUser, model);
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// MT share
|
||||||
|
String tenantDomain = (String)model.get(PostLookup.JSON_TENANT_DOMAIN);
|
||||||
|
if (tenantDomain == null) { tenantDomain = TenantService.DEFAULT_DOMAIN; }
|
||||||
|
|
||||||
|
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
||||||
|
{
|
||||||
|
public Boolean doWork() throws Exception
|
||||||
|
{
|
||||||
|
return canReadImpl(connectedUser, nodeRef);
|
||||||
|
}
|
||||||
|
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (permissionService == null)
|
// no nodeRef
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// MT share
|
|
||||||
String tenantDomain = (String)model.get(PostLookup.JSON_TENANT_DOMAIN);
|
|
||||||
if (tenantDomain == null) { tenantDomain = TenantService.DEFAULT_DOMAIN; }
|
|
||||||
|
|
||||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
|
||||||
{
|
|
||||||
public Boolean doWork() throws Exception
|
|
||||||
{
|
|
||||||
return canReadImpl(connectedUser, nodeRef);
|
|
||||||
}
|
|
||||||
}, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean canReadImpl(final String connectedUser, final NodeRef nodeRef) throws Exception
|
private boolean canReadImpl(final String connectedUser, final NodeRef nodeRef) throws Exception
|
||||||
{
|
{
|
||||||
// check for read permission
|
// check for read permission
|
||||||
@@ -498,6 +519,12 @@ public class LocalFeedTaskProcessor extends FeedTaskProcessor implements Applica
|
|||||||
|
|
||||||
protected Set<String> getFollowers(final String userId, String tenantDomain) throws Exception
|
protected Set<String> getFollowers(final String userId, String tenantDomain) throws Exception
|
||||||
{
|
{
|
||||||
|
if (useRemoteCallbacks)
|
||||||
|
{
|
||||||
|
// note: not implemented
|
||||||
|
throw new UnsupportedOperationException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
final Set<String> result = new HashSet<String>();
|
final Set<String> result = new HashSet<String>();
|
||||||
|
|
||||||
if (subscriptionService.isActive())
|
if (subscriptionService.isActive())
|
||||||
|
Reference in New Issue
Block a user