mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
fix for CLOUD-2150: Trashcan for network admins only shows their deleted content.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@57583 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -127,6 +127,15 @@
|
||||
<property name="cannedQueryRegistry">
|
||||
<ref bean="archivedNodesCannedQueryRegistry"/>
|
||||
</property>
|
||||
<property name="authorityService">
|
||||
<ref bean="authorityService"/>
|
||||
</property>
|
||||
<property name="tenantService">
|
||||
<ref bean="tenantService"/>
|
||||
</property>
|
||||
<property name="userNamesAreCaseSensitive">
|
||||
<value>${user.name.caseSensitive}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Archived Nodes -->
|
||||
@@ -135,10 +144,8 @@
|
||||
</bean>
|
||||
<bean name="archivedNodesCannedQueryFactory" class="org.alfresco.repo.node.archive.GetArchivedNodesCannedQueryFactory">
|
||||
<property name="registry" ref="archivedNodesCannedQueryRegistry"/>
|
||||
<property name="authorityService" ref="authorityService"/>
|
||||
<property name="tenantService" ref="tenantService"/>
|
||||
<property name="nodeDAO" ref="nodeDAO"/>
|
||||
<property name="nodeService" ref="nodeService"/>
|
||||
<property name="qnameDAO" ref="qnameDAO"/>
|
||||
<property name="cannedQueryDAO" ref="cannedQueryDAO"/>
|
||||
<property name="methodSecurity" ref="ArchivedNodes_security_listArchivedNodes"/>
|
||||
|
@@ -19,23 +19,14 @@
|
||||
|
||||
package org.alfresco.repo.node.archive;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.CannedQuery;
|
||||
import org.alfresco.query.CannedQueryPageDetails;
|
||||
import org.alfresco.query.CannedQueryParameters;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.query.AbstractQNameAwareCannedQueryFactory;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
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.security.AuthorityService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
@@ -46,19 +37,6 @@ import org.alfresco.util.ParameterCheck;
|
||||
*/
|
||||
public class GetArchivedNodesCannedQueryFactory extends AbstractQNameAwareCannedQueryFactory<ArchivedNodeEntity>
|
||||
{
|
||||
private AuthorityService authorityService;
|
||||
protected NodeService nodeService;
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CannedQuery<ArchivedNodeEntity> getCannedQuery(CannedQueryParameters parameters)
|
||||
{
|
||||
@@ -74,19 +52,19 @@ public class GetArchivedNodesCannedQueryFactory extends AbstractQNameAwareCanned
|
||||
* @param sortOrderAscending
|
||||
* @return an implementation that will execute the query
|
||||
*/
|
||||
public CannedQuery<ArchivedNodeEntity> getCannedQuery(NodeRef archiveStoreRootNodeRef,
|
||||
public CannedQuery<ArchivedNodeEntity> getCannedQuery(NodeRef archiveStoreRootNodeRef, QName assocTypeQName,
|
||||
String filter, boolean filterIgnoreCase, PagingRequest pagingRequest,
|
||||
boolean sortOrderAscending)
|
||||
{
|
||||
ParameterCheck.mandatory("archiveStoreRootNodeRef", archiveStoreRootNodeRef);
|
||||
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||
Long nodeId = (archiveStoreRootNodeRef == null) ? -1 : getNodeId(archiveStoreRootNodeRef);
|
||||
Long qnameId = (assocTypeQName == null) ? -1 : getQNameId(assocTypeQName);
|
||||
|
||||
int requestTotalCountMax = pagingRequest.getRequestTotalCountMax();
|
||||
|
||||
Pair<Long, Long> nodeIdAssocTypeIdPair = getNodeIdAssocTypeIdPair(archiveStoreRootNodeRef);
|
||||
GetArchivedNodesCannedQueryParams paramBean = new GetArchivedNodesCannedQueryParams(
|
||||
nodeIdAssocTypeIdPair.getFirst(), nodeIdAssocTypeIdPair.getSecond(), filter,
|
||||
filterIgnoreCase, getQNameId(ContentModel.PROP_NAME), sortOrderAscending);
|
||||
GetArchivedNodesCannedQueryParams paramBean = new GetArchivedNodesCannedQueryParams(nodeId,
|
||||
qnameId, filter, filterIgnoreCase, getQNameId(ContentModel.PROP_NAME),
|
||||
sortOrderAscending);
|
||||
|
||||
// page details
|
||||
CannedQueryPageDetails cqpd = new CannedQueryPageDetails(pagingRequest.getSkipCount(),
|
||||
@@ -100,39 +78,4 @@ public class GetArchivedNodesCannedQueryFactory extends AbstractQNameAwareCanned
|
||||
// return canned query instance
|
||||
return getCannedQuery(params);
|
||||
}
|
||||
|
||||
private Pair<Long, Long> getNodeIdAssocTypeIdPair(NodeRef archiveStoreRootNodeRef)
|
||||
{
|
||||
String userID = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (userID == null)
|
||||
{
|
||||
throw new AuthenticationException("Failed to authenticate. Current user, ", new Object[] { userID });
|
||||
}
|
||||
|
||||
if (archiveStoreRootNodeRef == null || !nodeService.exists(archiveStoreRootNodeRef))
|
||||
{
|
||||
throw new InvalidNodeRefException("Invalid archive store root node Ref.",
|
||||
archiveStoreRootNodeRef);
|
||||
}
|
||||
|
||||
if (authorityService.isAdminAuthority(userID))
|
||||
{
|
||||
return new Pair<Long, Long>(getNodeId(archiveStoreRootNodeRef),
|
||||
getQNameId(ContentModel.ASSOC_CHILDREN));
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ChildAssociationRef> list = nodeService.getChildrenByName(archiveStoreRootNodeRef,
|
||||
ContentModel.ASSOC_ARCHIVE_USER_LINK, Collections.singletonList(userID));
|
||||
|
||||
// Empty list means that the current user hasn't deleted anything yet.
|
||||
if (list.isEmpty())
|
||||
{
|
||||
return new Pair<Long, Long>(-1L, -1L);
|
||||
}
|
||||
NodeRef userArchive = list.get(0).getChildRef();
|
||||
return new Pair<Long, Long>(getNodeId(userArchive),
|
||||
getQNameId(ContentModel.ASSOC_ARCHIVED_LINK));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -188,4 +188,13 @@ public interface NodeArchiveService
|
||||
* @since 4.2
|
||||
*/
|
||||
public PagingResults<NodeRef> listArchivedNodes(ArchivedNodesCannedQueryBuilder cannedQueryBuilder);
|
||||
|
||||
/**
|
||||
* Check if the current user has authority to access the archived node.
|
||||
*
|
||||
* @param nodeRef
|
||||
* @return true if the currently authenticated user has authority to access
|
||||
* the archived node, otherwise false.
|
||||
*/
|
||||
public boolean hasFullAccess(NodeRef nodeRef);
|
||||
}
|
||||
|
@@ -39,6 +39,7 @@ import org.alfresco.repo.node.archive.RestoreNodeReport.RestoreStatus;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -48,6 +49,7 @@ 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.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -75,11 +77,14 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
|
||||
|
||||
private static Log logger = LogFactory.getLog(NodeArchiveServiceImpl.class);
|
||||
|
||||
private NodeService nodeService;
|
||||
protected NodeService nodeService;
|
||||
private PermissionService permissionService;
|
||||
private TransactionService transactionService;
|
||||
private JobLockService jobLockService;
|
||||
private AuthorityService authorityService;
|
||||
private NamedObjectRegistry<CannedQueryFactory<ArchivedNodeEntity>> cannedQueryRegistry;
|
||||
private TenantService tenantService;
|
||||
private boolean userNamesAreCaseSensitive = false;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
@@ -106,10 +111,25 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
|
||||
this.jobLockService = jobLockService;
|
||||
}
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public void setCannedQueryRegistry(NamedObjectRegistry<CannedQueryFactory<ArchivedNodeEntity>> cannedQueryRegistry)
|
||||
{
|
||||
this.cannedQueryRegistry = cannedQueryRegistry;
|
||||
}
|
||||
|
||||
public void setTenantService(TenantService tenantService)
|
||||
{
|
||||
this.tenantService = tenantService;
|
||||
}
|
||||
|
||||
public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive)
|
||||
{
|
||||
this.userNamesAreCaseSensitive = userNamesAreCaseSensitive;
|
||||
}
|
||||
|
||||
public NodeRef getArchivedNode(NodeRef originalNodeRef)
|
||||
{
|
||||
@@ -566,8 +586,9 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
|
||||
GetArchivedNodesCannedQueryFactory getArchivedNodesCannedQueryFactory = (GetArchivedNodesCannedQueryFactory) cannedQueryRegistry
|
||||
.getNamedObject(CANNED_QUERY_ARCHIVED_NODES_LIST);
|
||||
|
||||
Pair<NodeRef, QName> archiveNodeRefAssocTypePair = getArchiveNodeRefAssocTypePair(cannedQueryBuilder.getArchiveRootNodeRef());
|
||||
GetArchivedNodesCannedQuery cq = (GetArchivedNodesCannedQuery) getArchivedNodesCannedQueryFactory
|
||||
.getCannedQuery(cannedQueryBuilder.getArchiveRootNodeRef(),
|
||||
.getCannedQuery(archiveNodeRefAssocTypePair.getFirst(), archiveNodeRefAssocTypePair.getSecond(),
|
||||
cannedQueryBuilder.getFilter(),
|
||||
cannedQueryBuilder.isFilterIgnoreCase(),
|
||||
cannedQueryBuilder.getPagingRequest(),
|
||||
@@ -651,4 +672,80 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean hasFullAccess(NodeRef nodeRef)
|
||||
{
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
String currentUser = getCurrentUser();
|
||||
if (hasAdminAccess(currentUser))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
String archivedBy = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_ARCHIVED_BY);
|
||||
if(!userNamesAreCaseSensitive && archivedBy != null)
|
||||
{
|
||||
archivedBy = archivedBy.toLowerCase();
|
||||
}
|
||||
return currentUser.equals(archivedBy);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasAdminAccess(String userID)
|
||||
{
|
||||
return authorityService.isAdminAuthority(userID);
|
||||
}
|
||||
|
||||
private Pair<NodeRef, QName> getArchiveNodeRefAssocTypePair(final NodeRef archiveStoreRootNodeRef)
|
||||
{
|
||||
String currentUser = getCurrentUser();
|
||||
|
||||
if (archiveStoreRootNodeRef == null || !nodeService.exists(archiveStoreRootNodeRef))
|
||||
{
|
||||
throw new InvalidNodeRefException("Invalid archive store root node Ref.",
|
||||
archiveStoreRootNodeRef);
|
||||
}
|
||||
|
||||
if (hasAdminAccess(currentUser))
|
||||
{
|
||||
return new Pair<NodeRef, QName>(archiveStoreRootNodeRef, ContentModel.ASSOC_CHILDREN);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ChildAssociationRef> list = nodeService.getChildrenByName(archiveStoreRootNodeRef,
|
||||
ContentModel.ASSOC_ARCHIVE_USER_LINK,
|
||||
Collections.singletonList(currentUser));
|
||||
|
||||
// Empty list means that the current user hasn't deleted anything yet.
|
||||
if (list.isEmpty())
|
||||
{
|
||||
return new Pair<NodeRef, QName>(null, null);
|
||||
}
|
||||
NodeRef userArchive = list.get(0).getChildRef();
|
||||
return new Pair<NodeRef, QName>(userArchive, ContentModel.ASSOC_ARCHIVED_LINK);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCurrentUser()
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (currentUser == null)
|
||||
{
|
||||
throw new AccessDeniedException("No authenticated user; cannot get archived nodes.");
|
||||
}
|
||||
|
||||
if (!userNamesAreCaseSensitive
|
||||
&& !AuthenticationUtil.getSystemUserName().equals(
|
||||
tenantService.getBaseNameUser(currentUser)))
|
||||
{
|
||||
// user names are not case-sensitive
|
||||
currentUser = currentUser.toLowerCase();
|
||||
}
|
||||
return currentUser;
|
||||
}
|
||||
}
|
||||
|
@@ -953,13 +953,13 @@ public class ArchiveAndRestoreTest extends TestCase
|
||||
this.archiveStoreRootNodeRef, paging).filterIgnoreCase(true).build();
|
||||
|
||||
// Query the DB
|
||||
PagingResults<NodeRef> result = nodeArchiveService.listArchivedNodes(queryBuilder);
|
||||
PagingResults<NodeRef> result = runListArchivedNodesAsAdmin(queryBuilder);
|
||||
assertEquals("USER_B hasn't deleted anything yet.", 0, result.getPage().size());
|
||||
|
||||
// USER_B deletes "bb"
|
||||
nodeService.deleteNode(bb);
|
||||
|
||||
result = nodeArchiveService.listArchivedNodes(queryBuilder);
|
||||
result = runListArchivedNodesAsAdmin(queryBuilder);
|
||||
assertEquals("USER_B deleted only 1 item.", 1, result.getPage().size());
|
||||
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(USER_A);
|
||||
@@ -971,7 +971,7 @@ public class ArchiveAndRestoreTest extends TestCase
|
||||
this.archiveStoreRootNodeRef, paging)
|
||||
.filterIgnoreCase(true).build();
|
||||
|
||||
result = nodeArchiveService.listArchivedNodes(queryBuilder);
|
||||
result = runListArchivedNodesAsAdmin(queryBuilder);
|
||||
assertEquals("USER_A deleted only 1 item.", 1, result.getPage().size());
|
||||
assertEquals(QNAME_AA.getLocalName(),
|
||||
nodeService.getProperty(result.getPage().get(0), ContentModel.PROP_NAME));
|
||||
@@ -988,6 +988,18 @@ public class ArchiveAndRestoreTest extends TestCase
|
||||
assertEquals("Admin can retrieve all users' deleted nodes.", 2, result.getPage().size());
|
||||
}
|
||||
|
||||
private PagingResults<NodeRef> runListArchivedNodesAsAdmin(final ArchivedNodesCannedQueryBuilder queryBuilder)
|
||||
{
|
||||
return AuthenticationUtil.runAs(new RunAsWork<PagingResults<NodeRef>>()
|
||||
{
|
||||
@Override
|
||||
public PagingResults<NodeRef> doWork() throws Exception
|
||||
{
|
||||
return nodeArchiveService.listArchivedNodes(queryBuilder);
|
||||
}
|
||||
}, AuthenticationUtil.getAdminUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test listArchivedNodes sorted by ARCHIVED_DATE (DESC).
|
||||
*/
|
||||
|
Reference in New Issue
Block a user