diff --git a/config/alfresco/node-services-context.xml b/config/alfresco/node-services-context.xml
index 0ed7523bdb..9c58460a93 100644
--- a/config/alfresco/node-services-context.xml
+++ b/config/alfresco/node-services-context.xml
@@ -127,6 +127,15 @@
+
+
+
+
+
+
+
+ ${user.name.caseSensitive}
+
@@ -135,10 +144,8 @@
-
-
diff --git a/source/java/org/alfresco/repo/node/archive/GetArchivedNodesCannedQueryFactory.java b/source/java/org/alfresco/repo/node/archive/GetArchivedNodesCannedQueryFactory.java
index 5d011fb140..1fe1d2452a 100644
--- a/source/java/org/alfresco/repo/node/archive/GetArchivedNodesCannedQueryFactory.java
+++ b/source/java/org/alfresco/repo/node/archive/GetArchivedNodesCannedQueryFactory.java
@@ -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
{
- 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 getCannedQuery(CannedQueryParameters parameters)
{
@@ -74,19 +52,19 @@ public class GetArchivedNodesCannedQueryFactory extends AbstractQNameAwareCanned
* @param sortOrderAscending
* @return an implementation that will execute the query
*/
- public CannedQuery getCannedQuery(NodeRef archiveStoreRootNodeRef,
+ public CannedQuery 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 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 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(getNodeId(archiveStoreRootNodeRef),
- getQNameId(ContentModel.ASSOC_CHILDREN));
- }
- else
- {
- List 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(-1L, -1L);
- }
- NodeRef userArchive = list.get(0).getChildRef();
- return new Pair(getNodeId(userArchive),
- getQNameId(ContentModel.ASSOC_ARCHIVED_LINK));
- }
- }
}
diff --git a/source/java/org/alfresco/repo/node/archive/NodeArchiveService.java b/source/java/org/alfresco/repo/node/archive/NodeArchiveService.java
index c1ee932df3..5f2177f492 100644
--- a/source/java/org/alfresco/repo/node/archive/NodeArchiveService.java
+++ b/source/java/org/alfresco/repo/node/archive/NodeArchiveService.java
@@ -188,4 +188,13 @@ public interface NodeArchiveService
* @since 4.2
*/
public PagingResults 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);
}
diff --git a/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java b/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
index 437ad11e7d..db40799eeb 100644
--- a/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/archive/NodeArchiveServiceImpl.java
@@ -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> 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> 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 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 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(archiveStoreRootNodeRef, ContentModel.ASSOC_CHILDREN);
+ }
+ else
+ {
+ List 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(null, null);
+ }
+ NodeRef userArchive = list.get(0).getChildRef();
+ return new Pair(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;
+ }
}
diff --git a/source/test-java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java b/source/test-java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java
index ed0ce407ff..3bf9acbb22 100644
--- a/source/test-java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java
+++ b/source/test-java/org/alfresco/repo/node/archive/ArchiveAndRestoreTest.java
@@ -953,13 +953,13 @@ public class ArchiveAndRestoreTest extends TestCase
this.archiveStoreRootNodeRef, paging).filterIgnoreCase(true).build();
// Query the DB
- PagingResults result = nodeArchiveService.listArchivedNodes(queryBuilder);
+ PagingResults 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 runListArchivedNodesAsAdmin(final ArchivedNodesCannedQueryBuilder queryBuilder)
+ {
+ return AuthenticationUtil.runAs(new RunAsWork>()
+ {
+ @Override
+ public PagingResults doWork() throws Exception
+ {
+ return nodeArchiveService.listArchivedNodes(queryBuilder);
+ }
+ }, AuthenticationUtil.getAdminUserName());
+ }
+
/**
* Test listArchivedNodes sorted by ARCHIVED_DATE (DESC).
*/