Compare commits

..

18 Commits
12.2 ... 12.8

Author SHA1 Message Date
Travis CI User
6c68658476 [maven-release-plugin][skip ci] prepare release 12.8 2021-11-22 19:42:33 +00:00
tiagosalvado10
1bd439e0ec [MNT-22680] Bump surf-webscripts to 8.26 (#814) (#815)
(cherry picked from commit 20a617adef)
2021-11-22 18:47:28 +00:00
Travis CI User
72f84ee50b [maven-release-plugin][skip ci] prepare for next development iteration 2021-11-22 14:15:06 +00:00
Travis CI User
50f26b9137 [maven-release-plugin][skip ci] prepare release 12.7 2021-11-22 14:15:02 +00:00
evasques
b6b1cc3ea0 MNT-18700 - Dynamic Message bundles do not deploy/reload automatically (#805) (#810)
* Restored the ability to register dynamic messages on bootstrap
* Added unit tests on bootstrap to verify if the dynamic messages are registered on bootstrap
* Added unit tests for the Repo Admin Console regarding registering dynamic messages and classpath files

(cherry picked from commit be4fa79c76)
2021-11-22 10:35:27 +00:00
Travis CI User
0f1c1cdba1 [maven-release-plugin][skip ci] prepare for next development iteration 2021-11-17 22:20:28 +00:00
Travis CI User
841bc6844e [maven-release-plugin][skip ci] prepare release 12.6 2021-11-17 22:20:25 +00:00
tiagosalvado10
a5bdf47f00 [PRODSEC-5795] Bump surf-webscripts to 8.25 (#803) (#804)
(cherry picked from commit ee07bb635f)
2021-11-17 21:28:16 +00:00
Travis CI User
a0b279d1ff [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-25 14:21:26 +00:00
Travis CI User
fb967dfa9e [maven-release-plugin][skip ci] prepare release 12.5 2021-10-25 14:21:23 +00:00
Aleksandra Onych
f0a51e1347 MNT-21883 - Fix unshare content from smart folder (#765) (#772) 2021-10-25 15:00:23 +02:00
Travis CI User
42d56f9d20 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-19 11:04:24 +00:00
Travis CI User
3f31e4b1a2 [maven-release-plugin][skip ci] prepare release 12.4 2021-10-19 11:04:21 +00:00
Lev Belava
787a331869 MNT-21706 NodeService setAssociations list of elements is now handled. (#746) (#755)
MNT-21706 NodeService setAssociations list of elements is now handled.

(cherry picked from commit cbd45fcb3e)
2021-10-19 12:14:44 +02:00
Travis CI User
5ce3a3ddd6 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-06 11:41:46 +00:00
Travis CI User
9ed96ec593 [maven-release-plugin][skip ci] prepare release 12.3 2021-10-06 11:41:43 +00:00
montgolfiere
03b1fa8b09 ACS-2067: Fix probes for when DAU enabled (#700)
(cherry picked from commit 2ef97e0b23)
2021-10-06 11:38:04 +01:00
Travis CI User
d69f9b52c3 [maven-release-plugin][skip ci] prepare for next development iteration 2021-10-01 10:30:56 +00:00
38 changed files with 1136 additions and 481 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<dependencies>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<properties>

View File

@@ -9,6 +9,6 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<modules>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<developers>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<properties>

View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -61,7 +61,7 @@
<dependency.jackson-databind.version>2.12.4</dependency.jackson-databind.version>
<dependency.cxf.version>3.4.4</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.23</dependency.webscripts.version>
<dependency.webscripts.version>8.26</dependency.webscripts.version>
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
<dependency.mockito-core.version>3.11.2</dependency.mockito-core.version>
<dependency.mockito-all.version>1.10.19</dependency.mockito-all.version>
@@ -142,7 +142,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>12.2</tag>
<tag>12.8</tag>
</scm>
<distributionManagement>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<dependencies>

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.web.scripts.quickshare;
import java.util.HashMap;
@@ -31,10 +31,12 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.QuickShareModel;
import org.alfresco.repo.tenant.TenantUtil;
import org.alfresco.service.cmr.quickshare.InvalidSharedIdException;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.webscripts.Cache;
@@ -82,14 +84,15 @@ public class UnshareContentDelete extends AbstractQuickShareContent
try
{
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
Pair<String, NodeRef> pair = quickShareService.getTenantNodeRefFromSharedId(sharedId);
String networkTenantDomain = pair.getFirst();
String sharedBy = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedBy))
TenantUtil.runAsSystemTenant(() ->
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Can't perform unshare action: " + sharedId);
}
quickShareService.unshareContent(sharedId);
checkIfCanDeleteSharedLink(sharedId);
quickShareService.unshareContent(sharedId);
return null;
}, networkTenantDomain);
Map<String, Object> model = new HashMap<>(1);
model.put("success", Boolean.TRUE);
@@ -106,4 +109,14 @@ public class UnshareContentDelete extends AbstractQuickShareContent
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find: " + sharedId);
}
}
private void checkIfCanDeleteSharedLink(String sharedId) {
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
String sharedBy = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedBy))
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Can't perform unshare action: " + sharedId);
}
}
}

View File

@@ -274,15 +274,15 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
try
{
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
Pair<String, NodeRef> pair = quickShareService.getTenantNodeRefFromSharedId(sharedId);
String networkTenantDomain = pair.getFirst();
String sharedByUserId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedByUserId))
TenantUtil.runAsSystemTenant(() ->
{
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
}
quickShareService.unshareContent(sharedId);
checkIfCanDeleteSharedLink(sharedId);
quickShareService.unshareContent(sharedId);
return null;
}, networkTenantDomain);
}
catch (InvalidSharedIdException ex)
{
@@ -698,4 +698,14 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
throw new InvalidArgumentException("A valid recipientEmail must be specified.");
}
}
private void checkIfCanDeleteSharedLink(String sharedId) {
NodeRef nodeRef = quickShareService.getTenantNodeRefFromSharedId(sharedId).getSecond();
String sharedByUserId = (String)nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDBY);
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedByUserId))
{
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
}
}
}

View File

@@ -1070,7 +1070,7 @@
<property name="enabled" value="${system.api.discovery.enabled}" />
<property name="thumbnailService" ref="ThumbnailService" />
<property name="restApiDirectUrlConfig" ref="restApiDirectUrlConfig" />
<property name="contentService" ref="ContentService" />
<property name="contentService" ref="contentService" />
</bean>
<bean id="org.alfresco.rest.api.probes.ProbeEntityResource.get" class="org.alfresco.rest.api.probes.ProbeEntityResource">

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>12.2</version>
<version>12.8</version>
</parent>
<dependencies>

View File

@@ -415,12 +415,13 @@ implements TenantDeployer, DictionaryListener, /*TenantDictionaryListener, */Mes
for (NodeRef messageResource : nodeRefs)
{
String resourceName = (String) nodeService.getProperty(messageResource, ContentModel.PROP_NAME);
String bundleBaseName = messageService.getBaseBundleName(resourceName);
String messageResourcePath = nodeService.getPath(messageResource).toPrefixString(namespaceService);
String bundleBasePrefixedName = messageResourcePath.substring(messageResourcePath.lastIndexOf("/"));
String bundleBaseName = messageService.getBaseBundleName(bundleBasePrefixedName);
if (!resourceBundleBaseNames.contains(bundleBaseName))
{
messageService.registerResourceBundle(storeRef.toString() + repositoryLocation.getPath() + bundleBaseName);
resourceBundleBaseNames.add(bundleBaseName);
}
}

View File

@@ -1,30 +1,33 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.security.permissions.impl.acegi;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -46,8 +49,6 @@ import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.OwnableService;
@@ -59,6 +60,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* @author andyh
*/
@@ -395,61 +397,53 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
{
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
}
else if (StoreRef.class.isAssignableFrom(params[cad.parameter[0]]))
if (List.class.isAssignableFrom(params[cad.parameter[0]]))
{
StoreRef storeRef = getArgument(invocation, cad.parameter[0]);
if (storeRef != null)
List<?> listArgument = getArgument(invocation, cad.parameter[0]);
if (listArgument != null)
{
if (log.isDebugEnabled())
NodeRef listNodeRef;
Integer accessAbstainOrDeny = null;
for (Object listElement : listArgument)
{
log.debug("\tPermission test against the store - using permissions on the root node");
}
if (nodeService.exists(storeRef))
{
testNodeRef = nodeService.getRootNode(storeRef);
}
}
}
else if (NodeRef.class.isAssignableFrom(params[cad.parameter[0]]))
{
testNodeRef = getArgument(invocation, cad.parameter[0]);
if (log.isDebugEnabled())
{
if (testNodeRef != null)
{
if (nodeService.exists(testNodeRef))
listNodeRef = getNodeRef(listElement, nodeService);
Integer currentValue = shouldAbstainOrDeny(cad.required, listNodeRef, abstainForClassQNames, nodeService, permissionService);
if (currentValue != null)
{
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
if (currentValue == AccessDecisionVoter.ACCESS_DENIED)
{
return AccessDecisionVoter.ACCESS_DENIED;
}
else
{
accessAbstainOrDeny = currentValue;
}
}
else
{
log.debug("\tPermission test on non-existing node " +testNodeRef);
}
}
}
}
else if (ChildAssociationRef.class.isAssignableFrom(params[cad.parameter[0]]))
{
ChildAssociationRef testChildRef = getArgument(invocation, cad.parameter[0]);
if (testChildRef != null)
{
testNodeRef = testChildRef.getChildRef();
if (log.isDebugEnabled())
if (accessAbstainOrDeny != null)
{
if (nodeService.exists(testNodeRef))
{
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
}
else
{
log.debug("\tPermission test on non-existing node " + testNodeRef);
}
return accessAbstainOrDeny;
}
if((hasMethodEntry == null) || (hasMethodEntry.booleanValue()))
{
return AccessDecisionVoter.ACCESS_GRANTED;
}
else
{
return AccessDecisionVoter.ACCESS_DENIED;
}
}
}
else
{
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
Object testObject = getArgument(invocation, cad.parameter[0]);
//If the execution reaches here, then testNodeRef is always null
testNodeRef = getNodeRef(testObject, nodeService);
}
}
else if (cad.typeString.equals(ACL_ITEM))
@@ -584,44 +578,10 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
}
}
if (testNodeRef != null)
Integer accessAbstainOrDeny = shouldAbstainOrDeny(cad.required, testNodeRef, abstainForClassQNames, nodeService, permissionService);
if (accessAbstainOrDeny != null)
{
// now we know the node - we can abstain for certain types and aspects (eg. RM)
if(abstainForClassQNames.size() > 0)
{
// check node exists
if (nodeService.exists(testNodeRef))
{
QName typeQName = nodeService.getType(testNodeRef);
if(abstainForClassQNames.contains(typeQName))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
Set<QName> aspectQNames = nodeService.getAspects(testNodeRef);
for(QName abstain : abstainForClassQNames)
{
if(aspectQNames.contains(abstain))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
}
}
}
if (log.isDebugEnabled())
{
log.debug("\t\tNode ref is not null");
}
if (permissionService.hasPermission(testNodeRef, cad.required.toString()) == AccessStatus.DENIED)
{
if (log.isDebugEnabled())
{
log.debug("\t\tPermission is denied");
Thread.dumpStack();
}
return AccessDecisionVoter.ACCESS_DENIED;
}
return accessAbstainOrDeny;
}
}

View File

@@ -0,0 +1,175 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.security.permissions.impl.acegi;
import java.util.Set;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.PermissionService;
import org.alfresco.service.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods extracted from AclEntryVoter
*
* @author Lev Belava
*/
final class ACLEntryVoterUtils
{
private static final Logger LOG = LoggerFactory.getLogger(ACLEntryVoterUtils.class);
private ACLEntryVoterUtils()
{
}
/**
* Gets NodeRef for testObject based on inferred type
*
* @param testObject Tested object to work on
* @param nodeService Node service to perform checks on refs
* @return NodeRef for testObject or null if (testObject is null or StoreRef from testObject does not exist in the provided NodeService)
* @throws ACLEntryVoterException if testObject is not null and not one of a NodeRef or ChildAssociationRef types
*/
static NodeRef getNodeRef(Object testObject, NodeService nodeService)
{
if (testObject == null)
{
return null;
}
if (StoreRef.class.isAssignableFrom(testObject.getClass()))
{
LOG.debug("Permission test against the store - using permissions on the root node");
StoreRef storeRef = (StoreRef) testObject;
if (nodeService.exists(storeRef))
{
return nodeService.getRootNode(storeRef);
}
else
{
LOG.debug("StoreRef does not exist");
return null;
}
}
if (NodeRef.class.isAssignableFrom(testObject.getClass()))
{
NodeRef result = (NodeRef) testObject;
if (LOG.isDebugEnabled())
{
if (nodeService.exists(result))
{
LOG.debug("Permission test on node {}", nodeService.getPath(result));
}
else
{
LOG.debug("Permission test on non-existing node {}", result);
}
}
return result;
}
if (ChildAssociationRef.class.isAssignableFrom(testObject.getClass()))
{
ChildAssociationRef testChildRef = (ChildAssociationRef) testObject;
NodeRef result = testChildRef.getChildRef();
if (LOG.isDebugEnabled())
{
if (nodeService.exists(result))
{
LOG.debug("Permission test on node {}", nodeService.getPath(result));
}
else
{
LOG.debug("Permission test on non-existing node {}", result);
}
}
return result;
}
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
}
/**
* Checks if tested NodeRef instance is abstained or denied based on set of QNames to abstain and
*
* @param requiredPermissionReference Required permissions
* @param testNodeRef NodeRef to be verified
* @param abstainForClassQNames Set of QNames to abstain
* @param nodeService Node service to perform checks on tested NodeRef
* @param permissionService Permission service to check for required permissions
* @return null if testNodeRef is not abstained or denied, otherwise returns appropriate status.
*/
static Integer shouldAbstainOrDeny(SimplePermissionReference requiredPermissionReference, NodeRef testNodeRef, Set<QName> abstainForClassQNames,
NodeService nodeService, PermissionService permissionService)
{
if (testNodeRef == null)
{
return null;
}
LOG.debug("Node ref is not null");
if (abstainForClassQNames.size() > 0 && nodeService.exists(testNodeRef))
{
if (abstainForClassQNames.contains(nodeService.getType(testNodeRef)))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
Set<QName> testNodeRefAspects = nodeService.getAspects(testNodeRef);
for (QName abstain : abstainForClassQNames)
{
if (testNodeRefAspects.contains(abstain))
{
return AccessDecisionVoter.ACCESS_ABSTAIN;
}
}
}
if (AccessStatus.DENIED == permissionService.hasPermission(testNodeRef, requiredPermissionReference.toString()))
{
if (LOG.isDebugEnabled())
{
LOG.debug("Permission is denied");
Thread.dumpStack();
}
return AccessDecisionVoter.ACCESS_DENIED;
}
return null;
}
}

View File

@@ -209,6 +209,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.security.authentication.AuthorizationTest.class,
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.class,
org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtilsTest.class,
org.alfresco.repo.security.authentication.ChainingAuthenticationServiceTest.class,
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
org.alfresco.repo.version.common.VersionImplTest.class,

View File

@@ -31,17 +31,18 @@ import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import junit.framework.TestCase;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.NamespaceDAO;
import org.alfresco.repo.i18n.MessageService;
import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
@@ -50,6 +51,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -67,6 +69,8 @@ import org.apache.commons.logging.LogFactory;
import org.junit.experimental.categories.Category;
import org.springframework.context.ApplicationContext;
import junit.framework.TestCase;
/**
* @see RepoAdminServiceImpl
*
@@ -88,6 +92,7 @@ public class RepoAdminServiceImplTest extends TestCase
private NamespaceService namespaceService;
private BehaviourFilter behaviourFilter;
private DictionaryDAO dictionaryDAO;
private MessageService messageService;
final String modelPrefix = "model-";
final static String MKR = "{MKR}";
@@ -140,6 +145,7 @@ public class RepoAdminServiceImplTest extends TestCase
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
behaviourFilter = (BehaviourFilter)ctx.getBean("policyBehaviourFilter");
dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO");
messageService = (MessageService) ctx.getBean("MessageService");
DbNodeServiceImpl dbNodeService = (DbNodeServiceImpl)ctx.getBean("dbNodeService");
dbNodeService.setEnableTimestampPropagation(false);
@@ -865,8 +871,182 @@ public class RepoAdminServiceImplTest extends TestCase
}
}
}
//
// TODO - Test custom message management
//
// Test deploy bundle from classpath
public void testDeployMessageBundleFromClasspath() throws Exception
{
String bundleBaseName = "mycustommessages";
String resourceClasspath = "alfresco/extension/messages/" + bundleBaseName;
final String message_key = "mycustommessages.key1";
final String message_value_default = "This is a custom message";
final String message_value_fr = "Ceci est un message personnalis\\u00e9";
final String message_value_de = "Dies ist eine benutzerdefinierte Nachricht";
// Undeploy the bundle
if (repoAdminService.getMessageBundles().contains(bundleBaseName))
{
repoAdminService.undeployMessageBundle(bundleBaseName);
}
// Verify the custom bundle is registered
assertFalse("The custom bundle should not be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName));
// Depoly the message bundle
repoAdminService.deployMessageBundle(resourceClasspath);
// Reload the messages
repoAdminService.reloadMessageBundle(bundleBaseName);
// Verify the custom bundle is registered
assertTrue("The custom bundle should be deployed", repoAdminService.getMessageBundles().contains(bundleBaseName));
// Verify we have the messages for each locale
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
assertMessageValue("Cannot retrieve default message value", message_value_default, message_key, Locale.getDefault());
assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE);
assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY);
// Test deploy a non existent bundle
try
{
repoAdminService.deployMessageBundle("alfresco/extension/messages/inexistentbundle");
fail("Bundle was not supposed to be deployed");
}
catch (Exception e)
{
// Expected to fail
}
}
// Test deploy bundle from repo and reload bundles
public void testDeployMessageBundleFromRepo() throws Exception
{
final String bundleBaseName = "repoBundle";
final String message_key = "repoBundle.key1";
final String message_value = "Value 1";
final String message_value_fr = "Value FR";
final String message_value_de = "Value DE";
final String message_value_new = "New Value 1";
// Set location
NodeRef rootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
List<NodeRef> nodeRefs = searchService.selectNodes(rootNodeRef, "/app:company_home/app:dictionary/app:messages", null,
namespaceService, false);
assertEquals(1, nodeRefs.size());
NodeRef messagesNodeRef = nodeRefs.get(0);
// Clear messages of this bundle if they exist and are registered
clearRepoBundles(messagesNodeRef);
assertEquals(0, repoAdminService.getMessageBundles().size());
// Create and upload the message files
NodeRef messageNode_default = createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, null,
message_value);
createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.FRANCE.toString(), message_value_fr);
createMessagesNodeWithSingleKey(messagesNodeRef, bundleBaseName, message_key, Locale.GERMANY.toString(),
message_value_de);
// Reload the messages
repoAdminService.reloadMessageBundle(bundleBaseName);
// Verify we have the messages for each locale
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
assertMessageValue("Cannot retrieve default message value", message_value, message_key, Locale.getDefault());
assertMessageValue("Cannot retrieve french message value", message_value_fr, message_key, Locale.FRANCE);
assertMessageValue("Cannot retrieve german message value", message_value_de, message_key, Locale.GERMANY);
// Change the values
putContentInMessageNode(messageNode_default, message_key, message_value_new);
// Verify we still have the old value
assertMessageValue("Unexpected change of message value", message_value, message_key, Locale.getDefault());
// Reload the messages
repoAdminService.reloadMessageBundle(bundleBaseName);
// Verify new values
assertMessageValue("Change of message value not reflected", message_value_new, message_key, Locale.getDefault());
}
/**
* Create messages node
*/
private NodeRef createMessagesNodeWithSingleKey(NodeRef parentNode, String bundleName, String key, String locale,
String localeValue)
{
String msg_extension = ".properties";
String filename = bundleName + msg_extension;
String messageValue = localeValue;
if (locale != null)
{
filename = bundleName + "_" + locale + msg_extension;
}
// Create a model node
NodeRef messageNode = this.nodeService.createNode(
parentNode,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename),
ContentModel.TYPE_CONTENT,
Collections.<QName, Serializable> singletonMap(ContentModel.PROP_NAME, filename)
).getChildRef();
putContentInMessageNode(messageNode, key, messageValue);
return messageNode;
}
/**
* Write content of message node
*/
private void putContentInMessageNode(NodeRef nodeRef, String key, String value)
{
ContentWriter contentWriter = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
contentWriter.setEncoding("UTF-8");
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
String messagesString = key + "=" + value;
contentWriter.putContent(messagesString);
}
/**
* Clear Repo Bundle
*/
private void clearRepoBundles(NodeRef parentNode)
{
List<String> repoBundles = repoAdminService.getMessageBundles();
for (String repoBundle : repoBundles)
{
repoAdminService.undeployMessageBundle(repoBundle);
}
List<ChildAssociationRef> messageNodes = nodeService.getChildAssocs(parentNode);
for (ChildAssociationRef messageChildRef : messageNodes)
{
NodeRef messageNode = messageChildRef.getChildRef();
nodeService.deleteNode(messageNode);
}
}
/**
* Clear Repo Bundle
*/
private void assertMessageValue(String errorMessage, String expectedValue, String key, Locale locale)
{
transactionService.getRetryingTransactionHelper()
.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
assertEquals(errorMessage, expectedValue, messageService.getMessage(key, locale));
return null;
}
});
}
}

View File

@@ -25,9 +25,14 @@
*/
package org.alfresco.repo.dictionary;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
@@ -53,8 +58,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.transaction.UserTransaction;
import org.springframework.transaction.annotation.Transactional;
@Category(BaseSpringTestsCategory.class)
@@ -94,6 +97,14 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
"</model>";
public static final String MESSAGES_KEY = "my_bootstrap_test";
public static final String MESSAGES_VALUE = "My Message";
public static final String MESSAGES_VALUE_FR = "Mon message";
public static final String FOLDERNAME_MODELS = "models";
public static final String FOLDERNAME_MESSAGES = "messages";
public static final String BUNDLENAME_MESSAGES = "testBootstap";
public static final String FILENAME_MESSAGES_EXT = ".properties";
/** Behaviour filter */
private BehaviourFilter behaviourFilter;
@@ -123,7 +134,8 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
private UserTransaction txn;
private StoreRef storeRef;
private NodeRef rootNodeRef;
private NodeRef rootModelsNodeRef;
private NodeRef rootMessagesNodeRef;
@Before
public void before() throws Exception
@@ -151,7 +163,17 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
// Create the store and get the root node
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
this.rootNodeRef = this.nodeService.getRootNode(this.storeRef);
NodeRef rootNodeRef = this.nodeService.getRootNode(this.storeRef);
this.rootModelsNodeRef = this.nodeService
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MODELS), ContentModel.TYPE_FOLDER)
.getChildRef();
this.rootMessagesNodeRef = this.nodeService
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, FOLDERNAME_MESSAGES), ContentModel.TYPE_FOLDER)
.getChildRef();
txn.commit();
@@ -167,18 +189,20 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
this.bootstrap.setNamespaceService(this.namespaceService);
this.bootstrap.setMessageService(this.messageService);
this.bootstrap.setPolicyComponent(this.policyComponent);
RepositoryLocation location = new RepositoryLocation();
location.setStoreProtocol(this.storeRef.getProtocol());
location.setStoreId(this.storeRef.getIdentifier());
location.setQueryLanguage(RepositoryLocation.LANGUAGE_PATH);
// NOTE: we are not setting the path for now .. in doing so we are searching the root node only
List<RepositoryLocation> locations = new ArrayList<RepositoryLocation>();
locations.add(location);
this.bootstrap.setRepositoryModelsLocations(locations);
RepositoryLocation modelsLocation = new RepositoryLocation(this.storeRef,
this.nodeService.getPath(rootModelsNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
RepositoryLocation messagesLocation = new RepositoryLocation(this.storeRef,
this.nodeService.getPath(rootMessagesNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
List<RepositoryLocation> modelsLocations = new ArrayList<RepositoryLocation>();
modelsLocations.add(modelsLocation);
List<RepositoryLocation> messagesLocations = new ArrayList<RepositoryLocation>();
messagesLocations.add(messagesLocation);
this.bootstrap.setRepositoryModelsLocations(modelsLocations);
this.bootstrap.setRepositoryMessagesLocations(messagesLocations);
// register with dictionary service
this.bootstrap.register();
txn.commit();
@@ -224,7 +248,15 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
"Test model one",
"base1",
"prop1");
// Create a message file for the default locale
NodeRef messageNodeDefaultLoc = createMessagesNode(null, null);
// Create a message file for the french locale
createMessagesNode(Locale.FRANCE.toString(), MESSAGES_VALUE_FR);
// Construct baseBundleName for validation
String baseBundleName = storeRef.toString()
+ messageService.getBaseBundleName(nodeService.getPath(messageNodeDefaultLoc).toPrefixString(namespaceService));
// Check that the model is not in the dictionary yet
try
{
@@ -251,6 +283,12 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
QName.createQName("http://www.alfresco.org/model/test3DictionaryBootstrapFromRepo/1.0", "testModel3"));
assertNotNull(modelDefinition3);
// Check if the messages were registered correctly
assertTrue("The message bundle should be registered", messageService.getRegisteredBundles().contains(baseBundleName));
assertEquals("The default message value is not as expected", MESSAGES_VALUE, messageService.getMessage(MESSAGES_KEY));
assertEquals("The message value in french is not as expected", MESSAGES_VALUE_FR,
messageService.getMessage(MESSAGES_KEY, Locale.FRANCE));
txn.commit();
}
@@ -277,7 +315,7 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
{
// Create a model node
NodeRef model = this.nodeService.createNode(
this.rootNodeRef,
this.rootModelsNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{test}models"),
ContentModel.TYPE_DICTIONARY_MODEL).getChildRef();
@@ -300,6 +338,39 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
return model;
}
/**
* Create messages node
*
* @return NodeRef
*/
private NodeRef createMessagesNode(String locale, String localeValue)
{
String filename = BUNDLENAME_MESSAGES + FILENAME_MESSAGES_EXT;
String messageValue = MESSAGES_VALUE;
if (locale != null)
{
filename = BUNDLENAME_MESSAGES + "_" + locale + FILENAME_MESSAGES_EXT;
messageValue = localeValue;
}
// Create a model node
NodeRef messageNode = this.nodeService.createNode(
this.rootMessagesNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, filename),
ContentModel.TYPE_CONTENT,
Collections.<QName, Serializable> singletonMap(ContentModel.PROP_NAME, filename)
).getChildRef();
ContentWriter contentWriter = this.contentService.getWriter(messageNode, ContentModel.PROP_CONTENT, true);
contentWriter.setEncoding("UTF-8");
contentWriter.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
String messagesString = MESSAGES_KEY + "=" + messageValue;
contentWriter.putContent(messagesString);
return messageNode;
}
/**
*
* Gets the model string

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -96,6 +96,8 @@ public abstract class AbstractPermissionTest extends TestCase
protected NodeRef systemNodeRef;
protected NodeRef abstainedNode;
protected AuthenticationComponent authenticationComponent;
protected ModelDAO permissionModelDAO;
@@ -186,6 +188,8 @@ public abstract class AbstractPermissionTest extends TestCase
props = createPersonProperties(USER2_LEMUR);
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
abstainedNode= nodeService.createNode(rootNodeRef, ContentModel.ASSOC_FAILED_THUMBNAIL, system, ContentModel.TYPE_FAILED_THUMBNAIL).getChildRef();
// create an authentication object e.g. the user
if(authenticationDAO.userExists(USER1_ANDY))
{

View File

@@ -0,0 +1,181 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.security.permissions.impl.acegi;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.getNodeRef;
import static org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterUtils.shouldAbstainOrDeny;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Set;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
import org.alfresco.repo.security.permissions.impl.SimplePermissionReference;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.PermissionService;
import org.alfresco.service.namespace.QName;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ACLEntryVoterUtilsTest
{
private final NodeRef testNodeRef = new NodeRef("workspace://testNodeRef/testNodeRef");
private final NodeRef rootNodeRef = new NodeRef("workspace://rootNodeRef/rootNodeRef");
private final NodeRef refNodeForTestObject = new NodeRef("workspace://refNodeForTestObject/refNodeForTestObject");
private final NodeRef childRefNode = new NodeRef("workspace://childRefNode/childRefNode");
private final StoreRef testStoreNodeRef = new StoreRef("system://testStoreRefMock/testStoreRefMock");
private final SimplePermissionReference simplePermissionReference = SimplePermissionReference.getPermissionReference(QName.createQName("uri", "local"), "Write");
private final QName qNameToAbstain1 = QName.createQName("{test}testnode1");
private final QName qNameToAbstain2 = QName.createQName("{test}testnode2");
private final QName qNameToAbstain3 = QName.createQName("{test}testnode3");
private final QName qNameNotFromTheAbstainSet = QName.createQName("{test}testnodeAbstain");
private final Set<QName> qNamesToAbstain = Set.of(qNameToAbstain1, qNameToAbstain2, qNameToAbstain3);
@Mock
private PermissionService permissionServiceMock;
@Mock
private NodeService nodeServiceMock;
@Mock
private ChildAssociationRef childAssocRefMock;
@Before
public void setUp()
{
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.TRUE);
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.TRUE);
when(nodeServiceMock.getRootNode(testStoreNodeRef)).thenReturn(rootNodeRef);
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameNotFromTheAbstainSet);
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet));
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.DENIED);
}
@Test
public void returnsAccessDeniedFromPermissionService()
{
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_DENIED));
}
@Test
public void returnsNullOnNullTestObject()
{
assertThat(getNodeRef(null, nodeServiceMock), is(nullValue()));
}
@Test(expected = ACLEntryVoterException.class)
public void throwsExceptionWhenParameterIsNotNodeRefOrChildAssociationRef()
{
getNodeRef("TEST", nodeServiceMock);
}
@Test
public void returnsGivenTestNodeRefWhenStoreRefDoesNotExist()
{
when(nodeServiceMock.exists(testStoreNodeRef)).thenReturn(Boolean.FALSE);
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(nullValue()));
}
@Test
public void returnsRootNode()
{
assertThat(getNodeRef(testStoreNodeRef, nodeServiceMock), is(rootNodeRef));
}
@Test
public void returnsNodeRefFromTestObject()
{
assertThat(getNodeRef(refNodeForTestObject, nodeServiceMock), is(refNodeForTestObject));
}
@Test
public void returnsChildRefFromChildAssocRef()
{
when(childAssocRefMock.getChildRef()).thenReturn(childRefNode);
assertThat(getNodeRef(childAssocRefMock, nodeServiceMock), is(childRefNode));
}
@Test
public void returnsNullOnNullTestNodeRef()
{
assertThat(shouldAbstainOrDeny(simplePermissionReference, null, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnAbstainClassQnamesIsEmptyAndThereAreNoDeniedPermissions()
{
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, Collections.emptySet(), nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnTestNodeRefDoesNotExistAndThereAreNoDeniedPermissions()
{
when(nodeServiceMock.exists(testNodeRef)).thenReturn(Boolean.FALSE);
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsNullOnNodeTypeAndNodeAspectsAreNotInSetToAbstainAndThereAreNoDeniedPermissions()
{
when(permissionServiceMock.hasPermission(eq(testNodeRef), nullable(String.class))).thenReturn(AccessStatus.ALLOWED);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(nullValue()));
}
@Test
public void returnsAbstainWhenNodeRefTypeIsInSetToAbstain()
{
when(nodeServiceMock.getType(testNodeRef)).thenReturn(qNameToAbstain2);
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_ABSTAIN));
}
@Test
public void returnsAbstainWhenAtLeastOneAspectIsInSetToAbstain()
{
when(nodeServiceMock.getAspects(testNodeRef)).thenReturn(Set.of(qNameNotFromTheAbstainSet, qNameToAbstain3));
assertThat(shouldAbstainOrDeny(simplePermissionReference, testNodeRef, qNamesToAbstain, nodeServiceMock, permissionServiceMock),
is(AccessDecisionVoter.ACCESS_ABSTAIN));
}
}

View File

@@ -0,0 +1 @@
mycustommessages.key1=This is a custom message

View File

@@ -0,0 +1 @@
mycustommessages.key1=Dies ist eine benutzerdefinierte Nachricht

View File

@@ -0,0 +1 @@
mycustommessages.key1=Ceci est un message personnalis\u00e9