mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-17 14:21:39 +00:00
Merge remote-tracking branch 'origin/release/6.2.N' into release/6.2.N
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
2
pom.xml
2
pom.xml
@@ -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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Alfresco Community Repo Parent</name>
|
<name>Alfresco Community Repo Parent</name>
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -1831,6 +1831,19 @@ public class NodesImpl implements Nodes
|
|||||||
{
|
{
|
||||||
versionMajor = Boolean.valueOf(str);
|
versionMajor = Boolean.valueOf(str);
|
||||||
}
|
}
|
||||||
|
String versioningEnabledStringValue = parameters.getParameter("versioningEnabled");
|
||||||
|
if (null != versioningEnabledStringValue)
|
||||||
|
{
|
||||||
|
boolean versioningEnabled = Boolean.parseBoolean(versioningEnabledStringValue);
|
||||||
|
if (versioningEnabled)
|
||||||
|
{
|
||||||
|
versionMajor = (null != versionMajor) ? versionMajor : true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versionMajor = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
String versionComment = parameters.getParameter(PARAM_VERSION_COMMENT);
|
String versionComment = parameters.getParameter(PARAM_VERSION_COMMENT);
|
||||||
|
|
||||||
// Create the node
|
// Create the node
|
||||||
@@ -2331,6 +2344,11 @@ public class NodesImpl implements Nodes
|
|||||||
private void handleNodeRename(Map<QName, Serializable> props, NodeRef nodeRef)
|
private void handleNodeRename(Map<QName, Serializable> props, NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
Serializable nameProp = props.get(ContentModel.PROP_NAME);
|
Serializable nameProp = props.get(ContentModel.PROP_NAME);
|
||||||
|
handleNodeRename(nameProp, nodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNodeRename(Serializable nameProp, NodeRef nodeRef)
|
||||||
|
{
|
||||||
if ((nameProp != null))
|
if ((nameProp != null))
|
||||||
{
|
{
|
||||||
String currentName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
String currentName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||||
@@ -2705,6 +2723,7 @@ public class NodesImpl implements Nodes
|
|||||||
String fileName = parameters.getParameter(PARAM_NAME);
|
String fileName = parameters.getParameter(PARAM_NAME);
|
||||||
if (fileName != null)
|
if (fileName != null)
|
||||||
{
|
{
|
||||||
|
handleNodeRename(fileName, nodeRef);
|
||||||
// optionally rename, before updating the content
|
// optionally rename, before updating the content
|
||||||
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, fileName);
|
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, fileName);
|
||||||
}
|
}
|
||||||
@@ -2891,6 +2910,7 @@ public class NodesImpl implements Nodes
|
|||||||
String versionComment = null;
|
String versionComment = null;
|
||||||
String relativePath = null;
|
String relativePath = null;
|
||||||
String renditionNames = null;
|
String renditionNames = null;
|
||||||
|
boolean versioningEnabled = true;
|
||||||
|
|
||||||
Map<String, Object> qnameStrProps = new HashMap<>();
|
Map<String, Object> qnameStrProps = new HashMap<>();
|
||||||
Map<QName, Serializable> properties = null;
|
Map<QName, Serializable> properties = null;
|
||||||
@@ -2947,6 +2967,19 @@ public class NodesImpl implements Nodes
|
|||||||
case "renditions":
|
case "renditions":
|
||||||
renditionNames = getStringOrNull(field.getValue());
|
renditionNames = getStringOrNull(field.getValue());
|
||||||
break;
|
break;
|
||||||
|
case "versioningenabled":
|
||||||
|
String versioningEnabledStringValue = getStringOrNull(field.getValue());
|
||||||
|
if (null != versioningEnabledStringValue)
|
||||||
|
{
|
||||||
|
// MNT-22036 versioningenabled parameter was added to disable versioning of newly created nodes.
|
||||||
|
// The default API mechanism should not be changed/affected.
|
||||||
|
// Versioning is enabled by default when creating a node using form-data.
|
||||||
|
// To preserve this, versioningEnabled value must be 'true' for any given value typo/valuesNotSupported (except case-insensitive 'false')
|
||||||
|
// .equalsIgnoreCase("false") will return true only when the input value is 'false'
|
||||||
|
// !.equalsIgnoreCase("false") will return false only when the input value is 'false'
|
||||||
|
versioningEnabled = !versioningEnabledStringValue.equalsIgnoreCase("false");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -3025,6 +3058,8 @@ public class NodesImpl implements Nodes
|
|||||||
{
|
{
|
||||||
versionMajor = true;
|
versionMajor = true;
|
||||||
}
|
}
|
||||||
|
// MNT-22036 add versioningEnabled property for newly created nodes.
|
||||||
|
versionMajor = versioningEnabled ? versionMajor : null;
|
||||||
|
|
||||||
// Create a new file.
|
// Create a new file.
|
||||||
NodeRef nodeRef = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, assocTypeQName, parameters, versionMajor, versionComment);
|
NodeRef nodeRef = createNewFile(parentNodeRef, fileName, nodeTypeQName, content, properties, assocTypeQName, parameters, versionMajor, versionComment);
|
||||||
|
@@ -5605,6 +5605,279 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
|
|||||||
assertTrue(((ArrayList) (propUpdateResponse.get("custom:locations"))).size() == 1);
|
assertTrue(((ArrayList) (propUpdateResponse.get("custom:locations"))).size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void versioningEnabledMultipartNodeCreationTest() throws Exception
|
||||||
|
{
|
||||||
|
setRequestContext(user1);
|
||||||
|
String myNodeId = getMyNodeId();
|
||||||
|
// Test Scenarios:
|
||||||
|
// 1: majorVersion not set - versioningEnabled not set Expect: MAJOR version
|
||||||
|
// 2: majorVersion not set - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 3: majorVersion true - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 4: majorVersion false - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 5: majorVersion not set - versioningEnabled true Expect: MAJOR version
|
||||||
|
// 6: majorVersion true - versioningEnabled true Expect: MAJOR version
|
||||||
|
// 7: majorVersion false - versioningEnabled true Expect: Minor version
|
||||||
|
// 8: majorVersion not set - versioningEnabled False Expect: versioning disabled
|
||||||
|
// 9: majorVersion not set - versioningEnabled invalid Expect: MAJOR version
|
||||||
|
|
||||||
|
// Scenario 1:
|
||||||
|
String fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
File file = getResourceFile("quick-2.pdf");
|
||||||
|
MultiPartBuilder multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
|
||||||
|
MultiPartRequest reqBody = multiPartBuilder.build();
|
||||||
|
HttpResponse response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
Document documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
// Default behaviour, expect to be MAJOR Version 1.0
|
||||||
|
Map<String, Object> documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
// Scenario 2:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setVersioningEnabled("false");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
// Scenario 3:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setMajorVersion(true);
|
||||||
|
multiPartBuilder.setVersioningEnabled("false");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
// Scenario 4:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setMajorVersion(false);
|
||||||
|
multiPartBuilder.setVersioningEnabled("false");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
// Scenario 5:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setVersioningEnabled("true");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
// Scenario 6:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setMajorVersion(true);
|
||||||
|
multiPartBuilder.setVersioningEnabled("true");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
// Scenario 7:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setMajorVersion(false);
|
||||||
|
multiPartBuilder.setVersioningEnabled("true");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MINOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("0.1", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
// Scenario 8:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setVersioningEnabled("False");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
// Scenario 9:
|
||||||
|
fileName = "myfile" + UUID.randomUUID() + ".txt";
|
||||||
|
multiPartBuilder = MultiPartBuilder.create().setFileData(new FileData(fileName, file));
|
||||||
|
multiPartBuilder.setVersioningEnabled("invalid");
|
||||||
|
|
||||||
|
reqBody = multiPartBuilder.build();
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void versioningEnabledJSONNodeCreationTest() throws Exception
|
||||||
|
{
|
||||||
|
setRequestContext(user1);
|
||||||
|
String myNodeId = getMyNodeId();
|
||||||
|
|
||||||
|
// Test Scenarios:
|
||||||
|
// 1: majorVersion not set - versioningEnabled not set Expect: versioning disabled
|
||||||
|
// 2: majorVersion not set - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 3: majorVersion true - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 4: majorVersion false - versioningEnabled false Expect: versioning disabled
|
||||||
|
// 5: majorVersion not set - versioningEnabled true Expect: MAJOR version
|
||||||
|
// 6: majorVersion true - versioningEnabled true Expect: MAJOR version
|
||||||
|
// 7: majorVersion false - versioningEnabled true Expect: Minor version
|
||||||
|
// 8: majorVersion not set - versioningEnabled False Expect: versioning disabled
|
||||||
|
// 9: majorVersion not set - versioningEnabled invalid Expect: versioning disabled
|
||||||
|
// 10 majorVersion not set - versioningenabled true Expect: versioning disabled
|
||||||
|
|
||||||
|
Document d1 = new Document();
|
||||||
|
Map<String, String> requestHeaders = new HashMap<>();
|
||||||
|
|
||||||
|
//Scenario 1:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
d1.setNodeType(TYPE_CM_CONTENT);
|
||||||
|
|
||||||
|
HttpResponse response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
Document documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
Map<String, Object> documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 2:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","false");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 3:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","false");
|
||||||
|
requestHeaders.put("majorVersion","true");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 4:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","false");
|
||||||
|
requestHeaders.put("majorVersion","false");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 5:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","true");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
//Scenario 6:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","true");
|
||||||
|
requestHeaders.put("majorVersion","true");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MAJOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("1.0", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
//Scenario 7:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","true");
|
||||||
|
requestHeaders.put("majorVersion","false");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertEquals("MINOR", documentProperties.get("cm:versionType"));
|
||||||
|
assertEquals("0.1", documentProperties.get("cm:versionLabel"));
|
||||||
|
|
||||||
|
//Scenario 8:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","False");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 9:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningEnabled","invalid");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
|
||||||
|
//Scenario 10:
|
||||||
|
d1.setName("testDoc" + UUID.randomUUID());
|
||||||
|
requestHeaders = new HashMap<>();
|
||||||
|
requestHeaders.put("versioningenabled","true");
|
||||||
|
|
||||||
|
response = post(getNodeChildrenUrl(myNodeId), toJsonAsStringNonNull(d1),requestHeaders, null, null, 201);
|
||||||
|
documentResponse = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
|
||||||
|
documentProperties = documentResponse.getProperties();
|
||||||
|
assertNull(documentProperties);
|
||||||
|
}
|
||||||
|
|
||||||
@Test public void testAuditableProperties() throws Exception
|
@Test public void testAuditableProperties() throws Exception
|
||||||
{
|
{
|
||||||
setRequestContext(user1);
|
setRequestContext(user1);
|
||||||
@@ -5708,6 +5981,55 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
|
|||||||
assertTrue(currentPath.equals(expectedPath));
|
assertTrue(currentPath.equals(expectedPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrimaryPathVersion() throws Exception
|
||||||
|
{
|
||||||
|
setRequestContext(user1);
|
||||||
|
AuthenticationUtil.setFullyAuthenticatedUser(user1);
|
||||||
|
String myNodeId = getMyNodeId();
|
||||||
|
|
||||||
|
// /Company Home/User Homes/user<timestamp>/folder_A
|
||||||
|
String folderName = "folder_A";
|
||||||
|
Folder folder = createFolder(myNodeId, folderName);
|
||||||
|
NodeRef folderNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, folder.getId());
|
||||||
|
|
||||||
|
// /Company Home/User Homes/user<timestamp>/folder_A/testDoc<GUID>
|
||||||
|
String docName = "testDoc" + GUID.generate();
|
||||||
|
Document doc = new Document();
|
||||||
|
doc.setName(docName);
|
||||||
|
doc.setNodeType(TYPE_CM_CONTENT);
|
||||||
|
HttpResponse response = post(getNodeChildrenUrl(folderNodeRef.getId()), toJsonAsStringNonNull(doc), 201);
|
||||||
|
Document docResp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||||
|
NodeRef docNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, docResp.getId());
|
||||||
|
|
||||||
|
// Checks that current path and name match
|
||||||
|
String expectedPath1 = "/Company Home/User Homes/" + user1 + "/" + folderName + "/" + docName;
|
||||||
|
Path docPath1 = nodeService.getPath(docNodeRef);
|
||||||
|
Path.ChildAssocElement docPathLast1 = (Path.ChildAssocElement) docPath1.last();
|
||||||
|
String docLocalName1 = docPathLast1.getRef().getQName().getLocalName();
|
||||||
|
String currentPath1 = docPath1.toDisplayPath(nodeService, permissionService) + "/" + docLocalName1;
|
||||||
|
assertTrue(docName.equals(docLocalName1));
|
||||||
|
assertTrue(expectedPath1.equals(currentPath1));
|
||||||
|
|
||||||
|
// Upload document new content supplying a different name
|
||||||
|
String docName2 = "testDoc2" + GUID.generate();
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
params.put("name", docName2);
|
||||||
|
Document docResp2 = updateTextFileWithRandomContent(docNodeRef.getId(), 1024L, params);
|
||||||
|
NodeRef docNodeRef2 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, docResp2.getId());
|
||||||
|
|
||||||
|
// Checks new path and name after new version upload
|
||||||
|
String expectedPath2 = "/Company Home/User Homes/" + user1 + "/" + folderName + "/" + docName2;
|
||||||
|
Path docPath2 = nodeService.getPath(docNodeRef2);
|
||||||
|
Path.ChildAssocElement docPathLast2 = (Path.ChildAssocElement) docPath2.last();
|
||||||
|
String docLocalName2 = docPathLast2.getRef().getQName().getLocalName();
|
||||||
|
String currentPath2 = docPath2.toDisplayPath(nodeService, permissionService) + "/" + docLocalName2;
|
||||||
|
assertFalse(docLocalName1.equals(docLocalName2));
|
||||||
|
assertTrue(docName2.equals(docLocalName2));
|
||||||
|
assertFalse(expectedPath1.equals(currentPath2));
|
||||||
|
assertTrue(expectedPath2.equals(currentPath2));
|
||||||
|
}
|
||||||
|
|
||||||
private String getDataDictionaryNodeId() throws Exception
|
private String getDataDictionaryNodeId() throws Exception
|
||||||
{
|
{
|
||||||
Map params = new HashMap<>();
|
Map params = new HashMap<>();
|
||||||
|
@@ -43,7 +43,6 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i><b>multipart/form-data</b></i> builder.
|
* <i><b>multipart/form-data</b></i> builder.
|
||||||
@@ -57,6 +56,7 @@ public class MultiPartBuilder
|
|||||||
private String updateNodeRef;
|
private String updateNodeRef;
|
||||||
private String description;
|
private String description;
|
||||||
private String contentTypeQNameStr;
|
private String contentTypeQNameStr;
|
||||||
|
private String versioningEnabled;
|
||||||
private List<String> aspects = Collections.emptyList();
|
private List<String> aspects = Collections.emptyList();
|
||||||
private Boolean majorVersion;
|
private Boolean majorVersion;
|
||||||
private Boolean overwrite;
|
private Boolean overwrite;
|
||||||
@@ -76,6 +76,7 @@ public class MultiPartBuilder
|
|||||||
this.updateNodeRef = that.updateNodeRef;
|
this.updateNodeRef = that.updateNodeRef;
|
||||||
this.description = that.description;
|
this.description = that.description;
|
||||||
this.contentTypeQNameStr = that.contentTypeQNameStr;
|
this.contentTypeQNameStr = that.contentTypeQNameStr;
|
||||||
|
this.versioningEnabled = that.versioningEnabled;
|
||||||
this.aspects = new ArrayList<>(that.aspects);
|
this.aspects = new ArrayList<>(that.aspects);
|
||||||
this.majorVersion = that.majorVersion;
|
this.majorVersion = that.majorVersion;
|
||||||
this.overwrite = that.overwrite;
|
this.overwrite = that.overwrite;
|
||||||
@@ -125,6 +126,12 @@ public class MultiPartBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MultiPartBuilder setVersioningEnabled(String versioningEnabled)
|
||||||
|
{
|
||||||
|
this.versioningEnabled = versioningEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MultiPartBuilder setAspects(List<String> aspects)
|
public MultiPartBuilder setAspects(List<String> aspects)
|
||||||
{
|
{
|
||||||
this.aspects = aspects;
|
this.aspects = aspects;
|
||||||
@@ -278,6 +285,7 @@ public class MultiPartBuilder
|
|||||||
addPartIfNotNull(parts, "updatenoderef", updateNodeRef);
|
addPartIfNotNull(parts, "updatenoderef", updateNodeRef);
|
||||||
addPartIfNotNull(parts, "description", description);
|
addPartIfNotNull(parts, "description", description);
|
||||||
addPartIfNotNull(parts, "contenttype", contentTypeQNameStr);
|
addPartIfNotNull(parts, "contenttype", contentTypeQNameStr);
|
||||||
|
addPartIfNotNull(parts, "versioningenabled", versioningEnabled);
|
||||||
addPartIfNotNull(parts, "aspects", getCommaSeparated(aspects));
|
addPartIfNotNull(parts, "aspects", getCommaSeparated(aspects));
|
||||||
addPartIfNotNull(parts, "majorversion", majorVersion);
|
addPartIfNotNull(parts, "majorversion", majorVersion);
|
||||||
addPartIfNotNull(parts, "overwrite", overwrite);
|
addPartIfNotNull(parts, "overwrite", overwrite);
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>7.301-SNAPSHOT</version>
|
<version>7.308-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -177,13 +177,13 @@ public class CMISResultSetRow implements ResultSetRow
|
|||||||
context.setScore(getScore());
|
context.setScore(getScore());
|
||||||
for (Column column : query.getColumns())
|
for (Column column : query.getColumns())
|
||||||
{
|
{
|
||||||
// When an SCORE selector is included, score must be adapted to range 0..1 due to CMIS specification
|
if (column.getAlias().equals(columnName))
|
||||||
|
{
|
||||||
|
//When an SCORE selector is included, score must be adapted to range 0..1 due to CMIS specification
|
||||||
if (column.getFunction()!= null && column.getFunction().getName().equals(Score.NAME))
|
if (column.getFunction()!= null && column.getFunction().getName().equals(Score.NAME))
|
||||||
{
|
{
|
||||||
return getNormalisedScore();
|
return getNormalisedScore();
|
||||||
}
|
}
|
||||||
else if (column.getAlias().equals(columnName))
|
|
||||||
{
|
|
||||||
return column.getFunction().getValue(column.getFunctionArguments(), context);
|
return column.getFunction().getValue(column.getFunctionArguments(), context);
|
||||||
}
|
}
|
||||||
// Special case for one selector - ignore any table aliases
|
// Special case for one selector - ignore any table aliases
|
||||||
|
@@ -150,10 +150,24 @@ public final class DefaultSimpleCache<K extends Serializable, V extends Object>
|
|||||||
* @return <code>true</code> if the put resulted in a change in value, <code>false</code> otherwise.
|
* @return <code>true</code> if the put resulted in a change in value, <code>false</code> otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean putAndCheckUpdate(K key, V value)
|
public boolean putAndCheckUpdate(K key, V value)
|
||||||
|
{
|
||||||
|
return putAndCheckUpdate(key, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>put</code> method that may be used to check for updates in a thread-safe manner.
|
||||||
|
*
|
||||||
|
* @param includeNewCheck if true then we include the new value in the check
|
||||||
|
* @return <code>true</code> if the put resulted in a change in value,
|
||||||
|
* or if includeNewCheck is true and the put resulted in a new value,
|
||||||
|
* <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean putAndCheckUpdate(K key, V value, boolean includeNewCheck)
|
||||||
{
|
{
|
||||||
AbstractMap.SimpleImmutableEntry<K, V> kvp = new AbstractMap.SimpleImmutableEntry<K, V>(key, value);
|
AbstractMap.SimpleImmutableEntry<K, V> kvp = new AbstractMap.SimpleImmutableEntry<K, V>(key, value);
|
||||||
AbstractMap.SimpleImmutableEntry<K, V> priorKVP = cache.asMap().put(key, kvp);
|
AbstractMap.SimpleImmutableEntry<K, V> priorKVP = cache.asMap().put(key, kvp);
|
||||||
return priorKVP != null && (! priorKVP.equals(kvp));
|
|
||||||
|
return (includeNewCheck && priorKVP == null) || (priorKVP != null && (!priorKVP.equals(kvp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -35,6 +35,7 @@ public enum DeploymentMethod
|
|||||||
INSTALLER,
|
INSTALLER,
|
||||||
DOCKER_COMPOSE,
|
DOCKER_COMPOSE,
|
||||||
HELM_CHART,
|
HELM_CHART,
|
||||||
|
ANSIBLE,
|
||||||
/**
|
/**
|
||||||
* The distribution zip was used to lay down the ACS artifacts
|
* The distribution zip was used to lay down the ACS artifacts
|
||||||
*/
|
*/
|
||||||
|
@@ -394,6 +394,18 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// When node is copied when the aspect is applied, the sharedACLtoReplace will not match the children's ACLS
|
||||||
|
// to replace, we need to use the current one.
|
||||||
|
Long currentAcl = nodeDAO.getNodeAclId(nodeId);
|
||||||
|
|
||||||
|
if (nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL))
|
||||||
|
{
|
||||||
|
// If node has a pending acl, retrieve the sharedAclToReplace from node property. When the job calls
|
||||||
|
// this, it already does it but on move and copy operations, it uses the new parents old ACL.
|
||||||
|
sharedAclToReplace = (Long) nodeDAO.getNodeProperty(nodeId, ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Lazily retrieve/create the shared ACL
|
// Lazily retrieve/create the shared ACL
|
||||||
if (mergeFrom == null)
|
if (mergeFrom == null)
|
||||||
{
|
{
|
||||||
@@ -407,18 +419,15 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
|
|
||||||
List<NodeIdAndAclId> children = nodeDAO.getPrimaryChildrenAcls(nodeId);
|
List<NodeIdAndAclId> children = nodeDAO.getPrimaryChildrenAcls(nodeId);
|
||||||
|
|
||||||
if(children.size() > 0)
|
|
||||||
{
|
|
||||||
nodeDAO.setPrimaryChildrenSharedAclId(nodeId, sharedAclToReplace, mergeFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!propagateOnChildren)
|
if (!propagateOnChildren)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NodeIdAndAclId child : children)
|
for (NodeIdAndAclId child : children)
|
||||||
{
|
{
|
||||||
Long acl = child.getAclId();
|
//Use the current ACL instead of the stored value, it could've been changed meanwhile
|
||||||
|
Long acl = nodeDAO.getNodeAclId(child.getId());
|
||||||
|
|
||||||
if (acl == null)
|
if (acl == null)
|
||||||
{
|
{
|
||||||
@@ -426,12 +435,8 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if(acl.equals(mergeFrom))
|
|
||||||
// {
|
|
||||||
// setFixedAcls(child.getId(), inheritFrom, mergeFrom, sharedAclToReplace, changes, false);
|
|
||||||
// }
|
|
||||||
// Still has old shared ACL or already replaced
|
// Still has old shared ACL or already replaced
|
||||||
if(acl.equals(sharedAclToReplace) || acl.equals(mergeFrom))
|
if(acl.equals(sharedAclToReplace) || acl.equals(mergeFrom) || acl.equals(currentAcl))
|
||||||
{
|
{
|
||||||
propagateOnChildren = setFixAclPending(child.getId(), inheritFrom, mergeFrom, sharedAclToReplace, changes, false, asyncCall, propagateOnChildren);
|
propagateOnChildren = setFixAclPending(child.getId(), inheritFrom, mergeFrom, sharedAclToReplace, changes, false, asyncCall, propagateOnChildren);
|
||||||
}
|
}
|
||||||
@@ -457,6 +462,21 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// By doing an eager update of the direct children we canot see if another thread has changed the ACL
|
||||||
|
// between the time we get the child nodes and we update them. By updating the direct children last it is
|
||||||
|
// possible to verify if any child has changed meanwhile.
|
||||||
|
if(children.size() > 0)
|
||||||
|
{
|
||||||
|
nodeDAO.setPrimaryChildrenSharedAclId(nodeId, sharedAclToReplace, mergeFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When this is not executed triggered by the job, but a move or copy operation occures on a pending
|
||||||
|
// node, we don't want to apply the OLD ACL that was pending
|
||||||
|
if(nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL))
|
||||||
|
{
|
||||||
|
removePendingAclAspect(nodeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,14 +529,23 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
}
|
}
|
||||||
// set ASPECT_PENDING_FIX_ACL aspect on node to be later on processed with FixedAclUpdater amd switch flag
|
// set ASPECT_PENDING_FIX_ACL aspect on node to be later on processed with FixedAclUpdater amd switch flag
|
||||||
// FIXED_ACL_ASYNC_REQUIRED_KEY
|
// FIXED_ACL_ASYNC_REQUIRED_KEY
|
||||||
addFixedAclPendingAspect(nodeId, sharedAclToReplace, inheritFrom);
|
addFixedAclPendingAspect(nodeId, sharedAclToReplace, inheritFrom, mergeFrom);
|
||||||
AlfrescoTransactionSupport.bindResource(FixedAclUpdater.FIXED_ACL_ASYNC_REQUIRED_KEY, true);
|
AlfrescoTransactionSupport.bindResource(FixedAclUpdater.FIXED_ACL_ASYNC_REQUIRED_KEY, true);
|
||||||
// stop propagating on children nodes
|
// stop propagating on children nodes
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFixedAclPendingAspect(Long nodeId, Long sharedAclToReplace, Long inheritFrom)
|
private void addFixedAclPendingAspect(Long nodeId, Long sharedAclToReplace, Long inheritFrom, Long mergeFrom)
|
||||||
{
|
{
|
||||||
|
//If the node already has the pending ACL aspect, just update the new inheritFrom value
|
||||||
|
if (nodeDAO.hasNodeAspect(nodeId, ContentModel.ASPECT_PENDING_FIX_ACL))
|
||||||
|
{
|
||||||
|
Map<QName, Serializable> pendingAclProperties = new HashMap<>();
|
||||||
|
pendingAclProperties.put(ContentModel.PROP_INHERIT_FROM_ACL, inheritFrom);
|
||||||
|
nodeDAO.addNodeProperties(nodeId, pendingAclProperties);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Set<QName> aspect = new HashSet<>();
|
Set<QName> aspect = new HashSet<>();
|
||||||
aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
aspect.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
||||||
nodeDAO.addNodeAspects(nodeId, aspect);
|
nodeDAO.addNodeAspects(nodeId, aspect);
|
||||||
@@ -530,6 +559,17 @@ public class ADMAccessControlListDAO implements AccessControlListDAO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removePendingAclAspect(Long nodeId)
|
||||||
|
{
|
||||||
|
Set<QName> aspects = new HashSet<>(1);
|
||||||
|
aspects.add(ContentModel.ASPECT_PENDING_FIX_ACL);
|
||||||
|
Set<QName> pendingFixAclProperties = new HashSet<>();
|
||||||
|
pendingFixAclProperties.add(ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
||||||
|
pendingFixAclProperties.add(ContentModel.PROP_INHERIT_FROM_ACL);
|
||||||
|
nodeDAO.removeNodeAspects(nodeId, aspects);
|
||||||
|
nodeDAO.removeNodeProperties(nodeId, pendingFixAclProperties);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@@ -106,4 +106,6 @@ public interface AccessControlListDAO
|
|||||||
public void updateInheritance(Long childNodeId, Long oldParentAclId, Long newParentAclId);
|
public void updateInheritance(Long childNodeId, Long oldParentAclId, Long newParentAclId);
|
||||||
|
|
||||||
public void setFixedAcls(Long nodeId, Long inheritFrom, Long mergeFrom, Long sharedAclToReplace, List<AclChange> changes, boolean set);
|
public void setFixedAcls(Long nodeId, Long inheritFrom, Long mergeFrom, Long sharedAclToReplace, List<AclChange> changes, boolean set);
|
||||||
|
|
||||||
|
public void removePendingAclAspect(Long nodeId);
|
||||||
}
|
}
|
||||||
|
@@ -53,6 +53,7 @@ import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
|||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
@@ -149,7 +150,8 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
|
|||||||
|
|
||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
onInheritPermissionsDisabledDelegate = policyComponent.registerClassPolicy(PermissionServicePolicies.OnInheritPermissionsDisabled.class);
|
onInheritPermissionsDisabledDelegate = policyComponent
|
||||||
|
.registerClassPolicy(PermissionServicePolicies.OnInheritPermissionsDisabled.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GetNodesWithAspects
|
private class GetNodesWithAspects
|
||||||
@@ -262,26 +264,34 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
|
|||||||
{
|
{
|
||||||
log.debug(String.format("Processing node %s", nodeRef));
|
log.debug(String.format("Processing node %s", nodeRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Long nodeId = nodeDAO.getNodePair(nodeRef).getFirst();
|
final Long nodeId = nodeDAO.getNodePair(nodeRef).getFirst();
|
||||||
|
|
||||||
|
// MNT-22009 - If node was deleted and in archive store, remove the aspect and properties and do not
|
||||||
|
// process
|
||||||
|
if (nodeRef.getStoreRef().equals(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE))
|
||||||
|
{
|
||||||
|
accessControlListDAO.removePendingAclAspect(nodeId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// retrieve acl properties from node
|
// retrieve acl properties from node
|
||||||
Long inheritFrom = (Long) nodeDAO.getNodeProperty(nodeId,
|
Long inheritFrom = (Long) nodeDAO.getNodeProperty(nodeId, ContentModel.PROP_INHERIT_FROM_ACL);
|
||||||
ContentModel.PROP_INHERIT_FROM_ACL);
|
Long sharedAclToReplace = (Long) nodeDAO.getNodeProperty(nodeId, ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
||||||
Long sharedAclToReplace = (Long) nodeDAO.getNodeProperty(nodeId,
|
|
||||||
ContentModel.PROP_SHARED_ACL_TO_REPLACE);
|
|
||||||
|
|
||||||
// set inheritance using retrieved prop
|
// set inheritance using retrieved prop
|
||||||
accessControlListDAO.setInheritanceForChildren(nodeRef, inheritFrom, sharedAclToReplace,
|
accessControlListDAO.setInheritanceForChildren(nodeRef, inheritFrom, sharedAclToReplace, true);
|
||||||
true);
|
|
||||||
|
|
||||||
nodeDAO.removeNodeAspects(nodeId, aspects);
|
// Remove aspect
|
||||||
nodeDAO.removeNodeProperties(nodeId, PENDING_FIX_ACL_ASPECT_PROPS);
|
accessControlListDAO.removePendingAclAspect(nodeId);
|
||||||
|
|
||||||
if (!policyIgnoreUtil.ignorePolicy(nodeRef))
|
if (!policyIgnoreUtil.ignorePolicy(nodeRef))
|
||||||
{
|
{
|
||||||
boolean transformedToAsyncOperation = toBoolean((Boolean) AlfrescoTransactionSupport.getResource(FixedAclUpdater.FIXED_ACL_ASYNC_REQUIRED_KEY));
|
boolean transformedToAsyncOperation = toBoolean(
|
||||||
|
(Boolean) AlfrescoTransactionSupport.getResource(FixedAclUpdater.FIXED_ACL_ASYNC_REQUIRED_KEY));
|
||||||
|
|
||||||
OnInheritPermissionsDisabled onInheritPermissionsDisabledPolicy = onInheritPermissionsDisabledDelegate.get(ContentModel.TYPE_BASE);
|
OnInheritPermissionsDisabled onInheritPermissionsDisabledPolicy = onInheritPermissionsDisabledDelegate
|
||||||
|
.get(ContentModel.TYPE_BASE);
|
||||||
onInheritPermissionsDisabledPolicy.onInheritPermissionsDisabled(nodeRef, transformedToAsyncOperation);
|
onInheritPermissionsDisabledPolicy.onInheritPermissionsDisabled(nodeRef, transformedToAsyncOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,12 +405,8 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
|
|||||||
|
|
||||||
AclWorkProvider provider = new AclWorkProvider();
|
AclWorkProvider provider = new AclWorkProvider();
|
||||||
AclWorker worker = new AclWorker();
|
AclWorker worker = new AclWorker();
|
||||||
BatchProcessor<NodeRef> bp = new BatchProcessor<>(
|
BatchProcessor<NodeRef> bp = new BatchProcessor<>("FixedAclUpdater",
|
||||||
"FixedAclUpdater",
|
transactionService.getRetryingTransactionHelper(), provider, numThreads, maxItemBatchSize, applicationContext,
|
||||||
transactionService.getRetryingTransactionHelper(),
|
|
||||||
provider,
|
|
||||||
numThreads, maxItemBatchSize,
|
|
||||||
applicationContext,
|
|
||||||
log, 100);
|
log, 100);
|
||||||
int count = bp.process(worker, true);
|
int count = bp.process(worker, true);
|
||||||
return count;
|
return count;
|
||||||
@@ -413,7 +419,7 @@ public class FixedAclUpdater extends TransactionListenerAdapter implements Appli
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
jobLockRefreshCallback.isActive.set(false);
|
jobLockRefreshCallback.isActive.set(false);
|
||||||
if(lockToken != null)
|
if (lockToken != null)
|
||||||
{
|
{
|
||||||
jobLockService.releaseLock(lockToken, lockQName);
|
jobLockService.releaseLock(lockToken, lockQName);
|
||||||
}
|
}
|
||||||
|
@@ -764,7 +764,7 @@ deployment.service.targetLockRefreshTime=60000
|
|||||||
# How long to wait in mS from the last communication before deciding that deployment has failed, possibly
|
# How long to wait in mS from the last communication before deciding that deployment has failed, possibly
|
||||||
# the destination is no longer available?
|
# the destination is no longer available?
|
||||||
deployment.service.targetLockTimeout=3600000
|
deployment.service.targetLockTimeout=3600000
|
||||||
# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ZIP, QUICK_START)
|
# Deployment method used to deploy this Alfresco instance (DEFAULT, INSTALLER, DOCKER_COMPOSE, HELM_CHART, ANSIBLE, ZIP, QUICK_START)
|
||||||
deployment.method=DEFAULT
|
deployment.method=DEFAULT
|
||||||
|
|
||||||
#Invitation Service
|
#Invitation Service
|
||||||
|
@@ -136,6 +136,7 @@
|
|||||||
<property name="tenantAware" value="false" />
|
<property name="tenantAware" value="false" />
|
||||||
<property name="cacheStats" ref="cacheStatistics"/>
|
<property name="cacheStats" ref="cacheStatistics"/>
|
||||||
<property name="cacheStatsEnabled" value="${cache.immutableEntitySharedCache.tx.statsEnabled}"/>
|
<property name="cacheStatsEnabled" value="${cache.immutableEntitySharedCache.tx.statsEnabled}"/>
|
||||||
|
<property name="allowEqualsChecks" value="true" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -132,6 +132,45 @@ public class DefaultSimpleCacheTest extends SimpleCacheTestBase<DefaultSimpleCac
|
|||||||
assertEquals(true, cache.putAndCheckUpdate(104, null));
|
assertEquals(true, cache.putAndCheckUpdate(104, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void putAndCheckUpdateIncludeNewCheck()
|
||||||
|
{
|
||||||
|
// Put an initial value
|
||||||
|
cache.put(101, "101");
|
||||||
|
// Update it
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(101, "99101", true));
|
||||||
|
// Check the value really was updated
|
||||||
|
assertEquals("99101", cache.get(101));
|
||||||
|
|
||||||
|
// Precondition: no value for key 102
|
||||||
|
assertFalse(cache.contains(102));
|
||||||
|
// Put a value - and test the return
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(102, "102", true));
|
||||||
|
assertEquals("102", cache.get(102));
|
||||||
|
|
||||||
|
cache.put(103, null);
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(103, "103", true));
|
||||||
|
// Repeat the put, this should not be an update
|
||||||
|
assertEquals(false, cache.putAndCheckUpdate(103, "103", true));
|
||||||
|
|
||||||
|
assertFalse(cache.contains(104));
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, null, true));
|
||||||
|
// Repeat putting null - still not an update, as we had that value a moment ago.
|
||||||
|
assertEquals(false, cache.putAndCheckUpdate(104, null, true));
|
||||||
|
// Now an update
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, "104", true));
|
||||||
|
// Another update
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, "99104", true));
|
||||||
|
// Another update, back to null
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, null, true));
|
||||||
|
// Not an update - still null
|
||||||
|
assertEquals(false, cache.putAndCheckUpdate(104, null, true));
|
||||||
|
|
||||||
|
cache.remove(104);
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, "104", true));
|
||||||
|
assertEquals(true, cache.putAndCheckUpdate(104, null, true));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Timer-based tests are not ideal. An alternative approach is to factor out the CacheBuilder.newBuilder()
|
// TODO: Timer-based tests are not ideal. An alternative approach is to factor out the CacheBuilder.newBuilder()
|
||||||
// call to a protected method, override that in this test class to return a mock and use the mock to check
|
// call to a protected method, override that in this test class to return a mock and use the mock to check
|
||||||
// that the Cache is being configured correctly, e.g. assert that expireAfterWrite(int, TimeUnit) is called.
|
// that the Cache is being configured correctly, e.g. assert that expireAfterWrite(int, TimeUnit) is called.
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user