mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
461bc277c0 | ||
|
fb79ee27a8 | ||
|
e7a2992b60 | ||
|
1b396d5218 | ||
|
5d769b7059 | ||
|
3f5bdb8c6a | ||
|
9f87b99d72 | ||
|
f2bd6ca466 | ||
|
509ab36c82 | ||
|
dfc9ea2f90 | ||
|
0696401f34 | ||
|
42e476891f | ||
|
95d2426af4 | ||
|
e2df0ca4b4 | ||
|
5a03bde0dc | ||
|
e8f44a14e3 | ||
|
a83fc912e7 | ||
|
57c5a1c01a | ||
|
e7cbd1d2a7 | ||
|
da6e87e001 | ||
|
4197c29fce | ||
|
3d4785d5ae | ||
|
6c68658476 | ||
|
1bd439e0ec | ||
|
72f84ee50b | ||
|
50f26b9137 | ||
|
b6b1cc3ea0 | ||
|
0f1c1cdba1 | ||
|
841bc6844e | ||
|
a5bdf47f00 | ||
|
a0b279d1ff | ||
|
fb967dfa9e | ||
|
f0a51e1347 | ||
|
42d56f9d20 | ||
|
3f31e4b1a2 | ||
|
787a331869 | ||
|
5ce3a3ddd6 | ||
|
9ed96ec593 | ||
|
03b1fa8b09 | ||
|
d69f9b52c3 |
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -434,6 +434,11 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber),
|
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber),
|
||||||
sourceTypeRef,
|
sourceTypeRef,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
|
if (isUseVersionAssocIndex())
|
||||||
|
{
|
||||||
|
nodeService.setChildAssociationIndex(childAssocRef, getAllVersions(versionHistoryRef).size());
|
||||||
|
}
|
||||||
versionNodeRef = childAssocRef.getChildRef();
|
versionNodeRef = childAssocRef.getChildRef();
|
||||||
|
|
||||||
// add aspect with the standard version properties to the 'version' node
|
// add aspect with the standard version properties to the 'version' node
|
||||||
@@ -808,6 +813,11 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
|||||||
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber),
|
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS + "-" + versionNumber),
|
||||||
sourceTypeRef,
|
sourceTypeRef,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
|
if (isUseVersionAssocIndex())
|
||||||
|
{
|
||||||
|
nodeService.setChildAssociationIndex(childAssocRef, getAllVersions(versionHistoryRef).size());
|
||||||
|
}
|
||||||
NodeRef versionNodeRef = childAssocRef.getChildRef();
|
NodeRef versionNodeRef = childAssocRef.getChildRef();
|
||||||
|
|
||||||
// add aspect with the standard version properties to the 'version' node
|
// add aspect with the standard version properties to the 'version' node
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
const THUMBNAIL_NAME = "doclib",
|
const THUMBNAIL_NAME = "doclib",
|
||||||
TYPE_SITES = "st:sites",
|
TYPE_SITES = "st:sites",
|
||||||
|
SITES_PATH = "Sites/",
|
||||||
PREF_DOCUMENT_FAVOURITES = "org.alfresco.share.documents.favourites",
|
PREF_DOCUMENT_FAVOURITES = "org.alfresco.share.documents.favourites",
|
||||||
PREF_FOLDER_FAVOURITES = "org.alfresco.share.folders.favourites",
|
PREF_FOLDER_FAVOURITES = "org.alfresco.share.folders.favourites",
|
||||||
LIKES_SCHEME = "likesRatingScheme";
|
LIKES_SCHEME = "likesRatingScheme";
|
||||||
@@ -278,8 +279,39 @@ var ParseArgs =
|
|||||||
pathNode = path.length > 0 ? rootNode.childByNamePath(path) : (pathNode || rootNode);
|
pathNode = path.length > 0 ? rootNode.childByNamePath(path) : (pathNode || rootNode);
|
||||||
if (pathNode === null)
|
if (pathNode === null)
|
||||||
{
|
{
|
||||||
status.setCode(status.STATUS_NOT_FOUND, "Path not found: '" + path + "'");
|
// Path was not found in rootNode so a search attempt will be performed in companyHome
|
||||||
return null;
|
pathNode = path.length > 0 ? companyhome.childByNamePath(path) : null;
|
||||||
|
|
||||||
|
// At this point, if path hasn't been found yet, a site search will be executed (if path first element is a site)
|
||||||
|
if (pathNode === null)
|
||||||
|
{
|
||||||
|
if (path && path.length > 0)
|
||||||
|
{
|
||||||
|
var siteId;
|
||||||
|
var idx = path.startsWith("/") ? 1 : 0;
|
||||||
|
|
||||||
|
if (idx >= 0)
|
||||||
|
{
|
||||||
|
siteId = path.split("/")[idx];
|
||||||
|
if (siteId)
|
||||||
|
{
|
||||||
|
var siteNode = siteService.getSiteInfo(siteId);
|
||||||
|
if (siteNode !== null)
|
||||||
|
{
|
||||||
|
path = SITES_PATH + path;
|
||||||
|
pathNode = companyhome.childByNamePath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If path node is still null, it wasn't possible to find it and STATUS_NOT_FOUND will be returned
|
||||||
|
if (pathNode === null)
|
||||||
|
{
|
||||||
|
status.setCode(status.STATUS_NOT_FOUND, "Path not found: '" + path + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent location parameter adjustment
|
// Parent location parameter adjustment
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -198,4 +198,15 @@ public class UnlockFileTests extends WebDavTest
|
|||||||
.then().unlock()
|
.then().unlock()
|
||||||
.and().assertThat().hasStatus(HttpStatus.NO_CONTENT.value()).and().assertThat().isUnlocked();
|
.and().assertThat().hasStatus(HttpStatus.NO_CONTENT.value()).and().assertThat().isUnlocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestRail(section={TestGroup.PROTOCOLS, TestGroup.WEBDAV}, executionType= ExecutionType.SANITY,
|
||||||
|
description ="Checks no existent file is not locked (and status 404)")
|
||||||
|
@Test(groups = {TestGroup.PROTOCOLS, TestGroup.WEBDAV, TestGroup.SANITY})
|
||||||
|
public void checkLockStatusForNonExistentFile() throws Exception
|
||||||
|
{
|
||||||
|
testFile = FileModel.getRandomFileModel(FileType.TEXT_PLAIN, content);
|
||||||
|
webDavProtocol.authenticateUser(dataUser.getAdminUser()).
|
||||||
|
usingResource(testFile).
|
||||||
|
assertThat().isUnlocked().assertThat().hasStatus(HttpStatus.NOT_FOUND.value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
#%L
|
#%L
|
||||||
Alfresco Repository WAR Community
|
Alfresco Repository WAR Community
|
||||||
%%
|
%%
|
||||||
Copyright (C) 2005 - 2016 Alfresco Software Limited
|
Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
%%
|
%%
|
||||||
This file is part of the Alfresco software.
|
This file is part of the Alfresco software.
|
||||||
If the software was purchased under a paid Alfresco license, the terms of
|
If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -35,15 +35,6 @@
|
|||||||
<%@ page import="org.alfresco.service.cmr.module.ModuleInstallState" %>
|
<%@ page import="org.alfresco.service.cmr.module.ModuleInstallState" %>
|
||||||
<%@ page import="java.util.Calendar" %>
|
<%@ page import="java.util.Calendar" %>
|
||||||
|
|
||||||
<!-- Enterprise index-jsp placeholder -->
|
|
||||||
<%
|
|
||||||
// route WebDAV requests
|
|
||||||
if (request.getMethod().equalsIgnoreCase("PROPFIND") || request.getMethod().equalsIgnoreCase("OPTIONS"))
|
|
||||||
{
|
|
||||||
response.sendRedirect(request.getContextPath() + "/webdav/");
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
|
|
||||||
<%
|
<%
|
||||||
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(session.getServletContext());
|
WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(session.getServletContext());
|
||||||
SysAdminParams sysAdminParams = (SysAdminParams)context.getBean("sysAdminParams");
|
SysAdminParams sysAdminParams = (SysAdminParams)context.getBean("sysAdminParams");
|
||||||
|
6
pom.xml
6
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>12.2</version>
|
<version>12.15</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Alfresco Community Repo Parent</name>
|
<name>Alfresco Community Repo Parent</name>
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<dependency.jackson-databind.version>2.12.4</dependency.jackson-databind.version>
|
<dependency.jackson-databind.version>2.12.4</dependency.jackson-databind.version>
|
||||||
<dependency.cxf.version>3.4.4</dependency.cxf.version>
|
<dependency.cxf.version>3.4.4</dependency.cxf.version>
|
||||||
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
|
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
|
||||||
<dependency.webscripts.version>8.23</dependency.webscripts.version>
|
<dependency.webscripts.version>8.27</dependency.webscripts.version>
|
||||||
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
|
<dependency.bouncycastle.version>1.69</dependency.bouncycastle.version>
|
||||||
<dependency.mockito-core.version>3.11.2</dependency.mockito-core.version>
|
<dependency.mockito-core.version>3.11.2</dependency.mockito-core.version>
|
||||||
<dependency.mockito-all.version>1.10.19</dependency.mockito-all.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>
|
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||||
<tag>12.2</tag>
|
<tag>12.15</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.santuario</groupId>
|
<groupId>org.apache.santuario</groupId>
|
||||||
<artifactId>xmlsec</artifactId>
|
<artifactId>xmlsec</artifactId>
|
||||||
<version>1.5.8</version>
|
<version>2.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- newer version, see REPO-3133 -->
|
<!-- newer version, see REPO-3133 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Remote API
|
* Alfresco Remote API
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -90,7 +90,8 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
|
|||||||
protected CmisVersion cmisVersion;
|
protected CmisVersion cmisVersion;
|
||||||
protected TenantAdminService tenantAdminService;
|
protected TenantAdminService tenantAdminService;
|
||||||
|
|
||||||
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf
|
// pre-configured allow list of media/mime types, eg. specific types of images & also pdf
|
||||||
|
private Set<String> nonAttachContentTypes = Collections.emptySet();
|
||||||
|
|
||||||
public void setTenantAdminService(TenantAdminService tenantAdminService)
|
public void setTenantAdminService(TenantAdminService tenantAdminService)
|
||||||
{
|
{
|
||||||
@@ -137,9 +138,12 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
|
|||||||
this.cmisVersion = CmisVersion.fromValue(cmisVersion);
|
this.cmisVersion = CmisVersion.fromValue(cmisVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNonAttachContentTypes(Set<String> nonAttachWhiteList)
|
public void setNonAttachContentTypes(String nonAttachAllowListStr)
|
||||||
{
|
{
|
||||||
this.nonAttachContentTypes = nonAttachWhiteList;
|
if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
|
||||||
|
{
|
||||||
|
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized Descriptor getCurrentDescriptor()
|
protected synchronized Descriptor getCurrentDescriptor()
|
||||||
|
@@ -1,28 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Remote API
|
* Alfresco Remote API
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
package org.alfresco.repo.web.scripts.quickshare;
|
package org.alfresco.repo.web.scripts.quickshare;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -31,10 +31,12 @@ import java.util.Map;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.alfresco.model.QuickShareModel;
|
import org.alfresco.model.QuickShareModel;
|
||||||
|
import org.alfresco.repo.tenant.TenantUtil;
|
||||||
import org.alfresco.service.cmr.quickshare.InvalidSharedIdException;
|
import org.alfresco.service.cmr.quickshare.InvalidSharedIdException;
|
||||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
@@ -82,14 +84,15 @@ public class UnshareContentDelete extends AbstractQuickShareContent
|
|||||||
|
|
||||||
try
|
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);
|
TenantUtil.runAsSystemTenant(() ->
|
||||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedBy))
|
|
||||||
{
|
{
|
||||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Can't perform unshare action: " + sharedId);
|
checkIfCanDeleteSharedLink(sharedId);
|
||||||
}
|
quickShareService.unshareContent(sharedId);
|
||||||
quickShareService.unshareContent(sharedId);
|
return null;
|
||||||
|
}, networkTenantDomain);
|
||||||
|
|
||||||
Map<String, Object> model = new HashMap<>(1);
|
Map<String, Object> model = new HashMap<>(1);
|
||||||
model.put("success", Boolean.TRUE);
|
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);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -239,11 +239,15 @@ public class NodesImpl implements Nodes
|
|||||||
|
|
||||||
private ConcurrentHashMap<String,NodeRef> ddCache = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<String,NodeRef> ddCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf
|
// pre-configured allow list of media/mime types, eg. specific types of images & also pdf
|
||||||
|
private Set<String> nonAttachContentTypes = Collections.emptySet();
|
||||||
|
|
||||||
public void setNonAttachContentTypes(Set<String> nonAttachWhiteList)
|
public void setNonAttachContentTypes(String nonAttachAllowListStr)
|
||||||
{
|
{
|
||||||
this.nonAttachContentTypes = nonAttachWhiteList;
|
if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
|
||||||
|
{
|
||||||
|
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init()
|
public void init()
|
||||||
|
@@ -274,15 +274,15 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
|
|||||||
|
|
||||||
try
|
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);
|
TenantUtil.runAsSystemTenant(() ->
|
||||||
if (!quickShareService.canDeleteSharedLink(nodeRef, sharedByUserId))
|
|
||||||
{
|
{
|
||||||
throw new PermissionDeniedException("Can't perform unshare action: " + sharedId);
|
checkIfCanDeleteSharedLink(sharedId);
|
||||||
}
|
quickShareService.unshareContent(sharedId);
|
||||||
|
return null;
|
||||||
quickShareService.unshareContent(sharedId);
|
}, networkTenantDomain);
|
||||||
}
|
}
|
||||||
catch (InvalidSharedIdException ex)
|
catch (InvalidSharedIdException ex)
|
||||||
{
|
{
|
||||||
@@ -698,4 +698,14 @@ public class QuickShareLinksImpl implements QuickShareLinks, RecognizedParamsExt
|
|||||||
throw new InvalidArgumentException("A valid recipientEmail must be specified.");
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -508,19 +508,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="nodes.nonAttachContentTypes" class="org.springframework.beans.factory.config.SetFactoryBean">
|
|
||||||
<property name="sourceSet">
|
|
||||||
<set>
|
|
||||||
<value>application/pdf</value>
|
|
||||||
<value>image/jpeg</value>
|
|
||||||
<value>image/gif</value>
|
|
||||||
<value>image/png</value>
|
|
||||||
<value>image/tiff</value>
|
|
||||||
<value>image/bmp</value>
|
|
||||||
</set>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="nodes.personLookupProperties" class="org.springframework.beans.factory.config.SetFactoryBean">
|
<bean id="nodes.personLookupProperties" class="org.springframework.beans.factory.config.SetFactoryBean">
|
||||||
<property name="sourceSet">
|
<property name="sourceSet">
|
||||||
<set>
|
<set>
|
||||||
@@ -541,7 +528,7 @@
|
|||||||
<property name="quickShareLinks" ref="QuickShareLinks"/>
|
<property name="quickShareLinks" ref="QuickShareLinks"/>
|
||||||
<property name="behaviourFilter" ref="policyBehaviourFilter"/>
|
<property name="behaviourFilter" ref="policyBehaviourFilter"/>
|
||||||
<property name="ignoreTypes" ref="nodes.ignoreTypes"/>
|
<property name="ignoreTypes" ref="nodes.ignoreTypes"/>
|
||||||
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/>
|
<property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
|
||||||
<property name="personLookupProperties" ref="nodes.personLookupProperties"/>
|
<property name="personLookupProperties" ref="nodes.personLookupProperties"/>
|
||||||
<property name="poster" ref="activitiesPoster" />
|
<property name="poster" ref="activitiesPoster" />
|
||||||
<property name="smartStore" ref="smartStore"/>
|
<property name="smartStore" ref="smartStore"/>
|
||||||
@@ -1070,7 +1057,7 @@
|
|||||||
<property name="enabled" value="${system.api.discovery.enabled}" />
|
<property name="enabled" value="${system.api.discovery.enabled}" />
|
||||||
<property name="thumbnailService" ref="ThumbnailService" />
|
<property name="thumbnailService" ref="ThumbnailService" />
|
||||||
<property name="restApiDirectUrlConfig" ref="restApiDirectUrlConfig" />
|
<property name="restApiDirectUrlConfig" ref="restApiDirectUrlConfig" />
|
||||||
<property name="contentService" ref="ContentService" />
|
<property name="contentService" ref="contentService" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="org.alfresco.rest.api.probes.ProbeEntityResource.get" class="org.alfresco.rest.api.probes.ProbeEntityResource">
|
<bean id="org.alfresco.rest.api.probes.ProbeEntityResource.get" class="org.alfresco.rest.api.probes.ProbeEntityResource">
|
||||||
@@ -1113,7 +1100,7 @@
|
|||||||
<property name="version" value="1.0"/>
|
<property name="version" value="1.0"/>
|
||||||
<property name="cmisVersion" value="1.0"/>
|
<property name="cmisVersion" value="1.0"/>
|
||||||
<property name="tenantAdminService" ref="tenantAdminService"/>
|
<property name="tenantAdminService" ref="tenantAdminService"/>
|
||||||
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/>
|
<property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="cmisAtomPubDispatcher1.1" class="org.alfresco.opencmis.PublicApiAtomPubCMISDispatcher" init-method="init">
|
<bean id="cmisAtomPubDispatcher1.1" class="org.alfresco.opencmis.PublicApiAtomPubCMISDispatcher" init-method="init">
|
||||||
@@ -1125,7 +1112,7 @@
|
|||||||
<property name="version" value="1.1"/>
|
<property name="version" value="1.1"/>
|
||||||
<property name="cmisVersion" value="1.1"/>
|
<property name="cmisVersion" value="1.1"/>
|
||||||
<property name="tenantAdminService" ref="tenantAdminService"/>
|
<property name="tenantAdminService" ref="tenantAdminService"/>
|
||||||
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/>
|
<property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="cmisBrowserDispatcher1.1" class="org.alfresco.opencmis.PublicApiBrowserCMISDispatcher" init-method="init">
|
<bean id="cmisBrowserDispatcher1.1" class="org.alfresco.opencmis.PublicApiBrowserCMISDispatcher" init-method="init">
|
||||||
@@ -1137,7 +1124,7 @@
|
|||||||
<property name="version" value="1.1"/>
|
<property name="version" value="1.1"/>
|
||||||
<property name="cmisVersion" value="1.1"/>
|
<property name="cmisVersion" value="1.1"/>
|
||||||
<property name="tenantAdminService" ref="tenantAdminService"/>
|
<property name="tenantAdminService" ref="tenantAdminService"/>
|
||||||
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/>
|
<property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="webscript.org.alfresco.api.opencmis.OpenCMIS.get"
|
<bean id="webscript.org.alfresco.api.opencmis.OpenCMIS.get"
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
<#elseif v?is_number>
|
<#elseif v?is_number>
|
||||||
${v?c}
|
${v?c}
|
||||||
<#elseif v?is_string>
|
<#elseif v?is_string>
|
||||||
"${v?string}"
|
"${v?html}"
|
||||||
<#elseif v?is_hash>
|
<#elseif v?is_hash>
|
||||||
<#if v?keys?size gt maxDepth >
|
<#if v?keys?size gt maxDepth >
|
||||||
<#stop "Max depth of object achieved">
|
<#stop "Max depth of object achieved">
|
||||||
@@ -188,7 +188,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
|
|||||||
</tr>
|
</tr>
|
||||||
<#list result.children as n>
|
<#list result.children as n>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#" onclick="AdminConsole_childClick('${n.childRef}');return false;">${n.QName}</a></td>
|
<td><a href="#" onclick="AdminConsole_childClick('${n.childRef}');return false;">${n.QName?html}</a></td>
|
||||||
<td><a href="#" onclick="AdminConsole_childClick('${n.childRef}');return false;">${n.childRef}</a></td>
|
<td><a href="#" onclick="AdminConsole_childClick('${n.childRef}');return false;">${n.childRef}</a></td>
|
||||||
<td>${n.primary?string}</td>
|
<td>${n.primary?string}</td>
|
||||||
<td>${n.typeQName}</td>
|
<td>${n.typeQName}</td>
|
||||||
@@ -222,7 +222,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
|
|||||||
</tr>
|
</tr>
|
||||||
<#list result.parents as p>
|
<#list result.parents as p>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${p.name.prefixedName}</td>
|
<td>${p.name.prefixedName?html}</td>
|
||||||
<td>${p.parentTypeName.prefixedName}</td>
|
<td>${p.parentTypeName.prefixedName}</td>
|
||||||
<td><a href="#" onclick="AdminConsole_parentClick('${p.parentRef}');return false;">${p.parentRef}</a></td></td>
|
<td><a href="#" onclick="AdminConsole_parentClick('${p.parentRef}');return false;">${p.parentRef}</a></td></td>
|
||||||
<td>${p.primary?string}</td>
|
<td>${p.primary?string}</td>
|
||||||
@@ -280,7 +280,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
|
|||||||
<@section label=msg("nodebrowser.permissions") />
|
<@section label=msg("nodebrowser.permissions") />
|
||||||
<table id="perminfo-table" class="node">
|
<table id="perminfo-table" class="node">
|
||||||
<tr><td>${msg("nodebrowser.inherits")}: ${result.permissions.inherit?string}</td></tr>
|
<tr><td>${msg("nodebrowser.inherits")}: ${result.permissions.inherit?string}</td></tr>
|
||||||
<tr><td>${msg("nodebrowser.owner")}: ${result.permissions.owner!""}</td></tr>
|
<tr><td>${msg("nodebrowser.owner")}: <#if result.permissions.owner??>${result.permissions.owner?html}</#if></td></tr>
|
||||||
</table>
|
</table>
|
||||||
<table id="permissions-table" class="node grid">
|
<table id="permissions-table" class="node grid">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -291,7 +291,7 @@ ${url.serviceContext}/api/node/${nodeRef?replace("://","/")}/content;${prop?url}
|
|||||||
<#list result.permissions.entries as p>
|
<#list result.permissions.entries as p>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${p.permission}</td>
|
<td>${p.permission}</td>
|
||||||
<td>${p.authority}</td>
|
<td>${p.authority?html}</td>
|
||||||
<td>${p.accessStatus}</td>
|
<td>${p.accessStatus}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</#list>
|
</#list>
|
||||||
|
@@ -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>12.2</version>
|
<version>12.15</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -28,6 +28,7 @@ package org.alfresco.repo.content;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -102,6 +103,9 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
|
|||||||
private boolean ignoreEmptyContent;
|
private boolean ignoreEmptyContent;
|
||||||
|
|
||||||
private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
|
private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
|
||||||
|
|
||||||
|
/** pre-configured allow list of media/mime types, eg. specific types of images & also pdf */
|
||||||
|
private Set<String> nonAttachContentTypes = Collections.emptySet();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The policy component
|
* The policy component
|
||||||
@@ -150,6 +154,14 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
|
|||||||
this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
|
this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNonAttachContentTypes(String nonAttachAllowListStr)
|
||||||
|
{
|
||||||
|
if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
|
||||||
|
{
|
||||||
|
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||||
{
|
{
|
||||||
this.policyComponent = policyComponent;
|
this.policyComponent = policyComponent;
|
||||||
@@ -621,9 +633,19 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
|
|||||||
throw new DirectAccessUrlDisabledException("Direct access url isn't available.");
|
throw new DirectAccessUrlDisabledException("Direct access url isn't available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String contentUrl = getContentUrl(nodeRef);
|
ContentData contentData = getContentData(nodeRef, ContentModel.PROP_CONTENT);
|
||||||
|
// check that the content & URL is available
|
||||||
|
if (contentData == null || contentData.getContentUrl() == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("The supplied nodeRef " + nodeRef + " has no content.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String contentUrl = contentData.getContentUrl();
|
||||||
|
String contentMimetype = contentData.getMimetype();
|
||||||
String fileName = getFileName(nodeRef);
|
String fileName = getFileName(nodeRef);
|
||||||
|
|
||||||
validFor = adjustValidFor(validFor);
|
validFor = adjustValidFor(validFor);
|
||||||
|
attachment = adjustAttachment(nodeRef, contentMimetype, attachment);
|
||||||
|
|
||||||
DirectAccessUrl directAccessUrl = null;
|
DirectAccessUrl directAccessUrl = null;
|
||||||
if (store.isContentDirectUrlEnabled())
|
if (store.isContentDirectUrlEnabled())
|
||||||
@@ -676,4 +698,21 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
|
|||||||
}
|
}
|
||||||
return validFor;
|
return validFor;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private boolean adjustAttachment(NodeRef nodeRef, String mimeType, boolean attachmentIn)
|
||||||
|
{
|
||||||
|
boolean attachment = true;
|
||||||
|
if (! attachmentIn)
|
||||||
|
{
|
||||||
|
if ((nonAttachContentTypes != null) && (nonAttachContentTypes.contains(mimeType)))
|
||||||
|
{
|
||||||
|
attachment = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("Ignored attachment=false for " + nodeRef.getId() + " since " + mimeType + " is not in the whitelist for non-attach content types");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attachment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -415,12 +415,13 @@ implements TenantDeployer, DictionaryListener, /*TenantDictionaryListener, */Mes
|
|||||||
|
|
||||||
for (NodeRef messageResource : nodeRefs)
|
for (NodeRef messageResource : nodeRefs)
|
||||||
{
|
{
|
||||||
String resourceName = (String) nodeService.getProperty(messageResource, ContentModel.PROP_NAME);
|
String messageResourcePath = nodeService.getPath(messageResource).toPrefixString(namespaceService);
|
||||||
|
String bundleBasePrefixedName = messageResourcePath.substring(messageResourcePath.lastIndexOf("/"));
|
||||||
String bundleBaseName = messageService.getBaseBundleName(resourceName);
|
String bundleBaseName = messageService.getBaseBundleName(bundleBasePrefixedName);
|
||||||
|
|
||||||
if (!resourceBundleBaseNames.contains(bundleBaseName))
|
if (!resourceBundleBaseNames.contains(bundleBaseName))
|
||||||
{
|
{
|
||||||
|
messageService.registerResourceBundle(storeRef.toString() + repositoryLocation.getPath() + bundleBaseName);
|
||||||
resourceBundleBaseNames.add(bundleBaseName);
|
resourceBundleBaseNames.add(bundleBaseName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -683,6 +683,7 @@ public class RenditionServiceImpl implements
|
|||||||
log.debug("OnContentUpdate calling RenditionService2.render(\""+sourceNodeRef+"\", \""+renditionName+"\" so we switch to the new service.");
|
log.debug("OnContentUpdate calling RenditionService2.render(\""+sourceNodeRef+"\", \""+renditionName+"\" so we switch to the new service.");
|
||||||
}
|
}
|
||||||
useRenditionService2 = true;
|
useRenditionService2 = true;
|
||||||
|
renditionService2.clearRenditionContentData(sourceNodeRef, renditionName);
|
||||||
renditionService2.render(sourceNodeRef, renditionName);
|
renditionService2.render(sourceNodeRef, renditionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -538,9 +538,8 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
}
|
}
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("Set rendition hashcode " + transformContentHashCode + " and ThumbnailLastModified for " + renditionName);
|
logger.debug("Set ThumbnailLastModified for " + renditionName);
|
||||||
}
|
}
|
||||||
nodeService.setProperty(renditionNode, RenditionModel.PROP_RENDITION_CONTENT_HASH_CODE, transformContentHashCode);
|
|
||||||
setThumbnailLastModified(sourceNodeRef, renditionName);
|
setThumbnailLastModified(sourceNodeRef, renditionName);
|
||||||
|
|
||||||
if (transformInputStream != null)
|
if (transformInputStream != null)
|
||||||
@@ -554,6 +553,11 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
contentWriter.setEncoding(DEFAULT_ENCODING);
|
contentWriter.setEncoding(DEFAULT_ENCODING);
|
||||||
ContentWriter renditionWriter = contentWriter;
|
ContentWriter renditionWriter = contentWriter;
|
||||||
renditionWriter.putContent(transformInputStream);
|
renditionWriter.putContent(transformInputStream);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Set rendition hashcode for " + renditionName);
|
||||||
|
}
|
||||||
|
nodeService.setProperty(renditionNode, RenditionModel.PROP_RENDITION_CONTENT_HASH_CODE, transformContentHashCode);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -563,16 +567,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serializable content = nodeService.getProperty(renditionNode, PROP_CONTENT);
|
clearRenditionContentData(renditionNode);
|
||||||
if (content != null)
|
|
||||||
{
|
|
||||||
nodeService.removeProperty(renditionNode, PROP_CONTENT);
|
|
||||||
nodeService.removeProperty(renditionNode, PROP_RENDITION_CONTENT_HASH_CODE);
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Cleared rendition content and hashcode");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sourceHasAspectRenditioned)
|
if (!sourceHasAspectRenditioned)
|
||||||
@@ -736,6 +731,43 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears source nodeRef rendition content and content hash code using supplied rendition name
|
||||||
|
*
|
||||||
|
* @param sourceNodeRef
|
||||||
|
* @param renditionName
|
||||||
|
*/
|
||||||
|
public void clearRenditionContentData(NodeRef sourceNodeRef, String renditionName)
|
||||||
|
{
|
||||||
|
clearRenditionContentData(getRenditionNode(sourceNodeRef, renditionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears supplied rendition node content (if exists) and content hash code
|
||||||
|
*
|
||||||
|
* @param renditionNode
|
||||||
|
*/
|
||||||
|
private void clearRenditionContentData(NodeRef renditionNode)
|
||||||
|
{
|
||||||
|
if (renditionNode != null)
|
||||||
|
{
|
||||||
|
Serializable content = nodeService.getProperty(renditionNode, PROP_CONTENT);
|
||||||
|
if (content != null)
|
||||||
|
{
|
||||||
|
nodeService.removeProperty(renditionNode, PROP_CONTENT);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Cleared rendition content");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodeService.removeProperty(renditionNode, PROP_RENDITION_CONTENT_HASH_CODE);
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Cleared rendition hashcode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method checks whether the specified source node is of a content class which has been registered for
|
* This method checks whether the specified source node is of a content class which has been registered for
|
||||||
* rendition prevention.
|
* rendition prevention.
|
||||||
@@ -886,6 +918,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(renditionName);
|
RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(renditionName);
|
||||||
if (renditionDefinition != null)
|
if (renditionDefinition != null)
|
||||||
{
|
{
|
||||||
|
clearRenditionContentData(sourceNodeRef, renditionName);
|
||||||
render(sourceNodeRef, renditionName);
|
render(sourceNodeRef, renditionName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -1,30 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
* provided under the following open source license terms:
|
* provided under the following open source license terms:
|
||||||
*
|
*
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
* 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
|
* 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
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
package org.alfresco.repo.security.permissions.impl.acegi;
|
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.io.Serializable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
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.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
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.AuthenticationService;
|
||||||
import org.alfresco.service.cmr.security.AuthorityService;
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
import org.alfresco.service.cmr.security.OwnableService;
|
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.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author andyh
|
* @author andyh
|
||||||
*/
|
*/
|
||||||
@@ -395,61 +397,53 @@ public class ACLEntryVoter implements AccessDecisionVoter, InitializingBean
|
|||||||
{
|
{
|
||||||
throw new ACLEntryVoterException("The specified parameter is not a NodeRef or ChildAssociationRef");
|
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]);
|
List<?> listArgument = getArgument(invocation, cad.parameter[0]);
|
||||||
if (storeRef != null)
|
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");
|
listNodeRef = getNodeRef(listElement, nodeService);
|
||||||
}
|
Integer currentValue = shouldAbstainOrDeny(cad.required, listNodeRef, abstainForClassQNames, nodeService, permissionService);
|
||||||
if (nodeService.exists(storeRef))
|
|
||||||
{
|
if (currentValue != null)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
if (accessAbstainOrDeny != null)
|
||||||
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 (nodeService.exists(testNodeRef))
|
return accessAbstainOrDeny;
|
||||||
{
|
|
||||||
log.debug("\tPermission test on node " + nodeService.getPath(testNodeRef));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log.debug("\tPermission test on non-existing node " + testNodeRef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if((hasMethodEntry == null) || (hasMethodEntry.booleanValue()))
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AccessDecisionVoter.ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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))
|
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)
|
return accessAbstainOrDeny;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2017 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -640,7 +640,7 @@ public class ThumbnailServiceImpl implements ThumbnailService,
|
|||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
ContentData content = (ContentData) this.nodeService.getProperty(thumbnailNode, ContentModel.PROP_CONTENT);
|
ContentData content = (ContentData) this.nodeService.getProperty(thumbnailNode, ContentModel.PROP_CONTENT);
|
||||||
// (MNT-17162) A thumbnail with an empty content is cached for post-transaction removal, to prevent the delete in read-only transactions.
|
// (MNT-17162) A thumbnail with an empty content is cached for post-transaction removal, to prevent the delete in read-only transactions.
|
||||||
if (content.getSize() == 0)
|
if (content == null || content.getSize() == 0)
|
||||||
{
|
{
|
||||||
TransactionalResourceHelper.getSet(THUMBNAIL_TO_DELETE_NODES).add(thumbnailNode);
|
TransactionalResourceHelper.getSet(THUMBNAIL_TO_DELETE_NODES).add(thumbnailNode);
|
||||||
TransactionSupportUtil.bindListener(this.thumbnailsToDeleteTransactionListener, 0);
|
TransactionSupportUtil.bindListener(this.thumbnailsToDeleteTransactionListener, 0);
|
||||||
|
@@ -84,6 +84,7 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
|
|||||||
private static Log logger = LogFactory.getLog(Version2ServiceImpl.class);
|
private static Log logger = LogFactory.getLog(Version2ServiceImpl.class);
|
||||||
|
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
private boolean useVersionAssocIndex = false;
|
||||||
|
|
||||||
private ExtendedTrait<VersionServiceTrait> versionServiceTrait;
|
private ExtendedTrait<VersionServiceTrait> versionServiceTrait;
|
||||||
|
|
||||||
@@ -96,7 +97,23 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
|
|||||||
{
|
{
|
||||||
this.permissionService = permissionService;
|
this.permissionService = permissionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to use child association index on versions. This helps ordering versions when sequential IDs are not
|
||||||
|
* guaranteed by the DBMS.
|
||||||
|
*
|
||||||
|
* @param useVersionAssocIndex
|
||||||
|
*/
|
||||||
|
public void setUseVersionAssocIndex(boolean useVersionAssocIndex)
|
||||||
|
{
|
||||||
|
this.useVersionAssocIndex = useVersionAssocIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseVersionAssocIndex()
|
||||||
|
{
|
||||||
|
return useVersionAssocIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise method
|
* Initialise method
|
||||||
*/
|
*/
|
||||||
@@ -506,9 +523,12 @@ public class Version2ServiceImpl extends VersionServiceImpl implements VersionSe
|
|||||||
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS+"-"+versionNumber), // TODO - testing - note: all children (of a versioned node) will have the same version number, maybe replace with a version sequence of some sort 001-...00n
|
QName.createQName(Version2Model.NAMESPACE_URI, Version2Model.CHILD_VERSIONS+"-"+versionNumber), // TODO - testing - note: all children (of a versioned node) will have the same version number, maybe replace with a version sequence of some sort 001-...00n
|
||||||
sourceTypeRef,
|
sourceTypeRef,
|
||||||
nodeDetails.getProperties());
|
nodeDetails.getProperties());
|
||||||
|
if (isUseVersionAssocIndex())
|
||||||
|
{
|
||||||
|
nodeService.setChildAssociationIndex(childAssocRef, getAllVersions(versionHistoryRef).size());
|
||||||
|
}
|
||||||
versionNodeRef = childAssocRef.getChildRef();
|
versionNodeRef = childAssocRef.getChildRef();
|
||||||
|
|
||||||
// NOTE: special ML case - see also MultilingualContentServiceImpl.makeMLContainer
|
// NOTE: special ML case - see also MultilingualContentServiceImpl.makeMLContainer
|
||||||
if (sourceTypeRef.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
|
if (sourceTypeRef.equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
|
||||||
{
|
{
|
||||||
|
@@ -164,6 +164,9 @@
|
|||||||
<property name="systemWideDirectUrlConfig" >
|
<property name="systemWideDirectUrlConfig" >
|
||||||
<ref bean="systemWideDirectUrlConfig" />
|
<ref bean="systemWideDirectUrlConfig" />
|
||||||
</property>
|
</property>
|
||||||
|
<property name="nonAttachContentTypes">
|
||||||
|
<value>${content.nonAttach.mimetypes}</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="contentService" parent="baseContentService">
|
<bean id="contentService" parent="baseContentService">
|
||||||
|
@@ -488,6 +488,9 @@
|
|||||||
<property name="versionComparatorClass">
|
<property name="versionComparatorClass">
|
||||||
<value>${version.store.versionComparatorClass}</value>
|
<value>${version.store.versionComparatorClass}</value>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="useVersionAssocIndex">
|
||||||
|
<value>${version.store.useVersionAssocIndex}</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="versionNodeService" class="org.alfresco.repo.version.Node2ServiceImpl">
|
<bean id="versionNodeService" class="org.alfresco.repo.version.Node2ServiceImpl">
|
||||||
|
@@ -382,6 +382,14 @@ version.store.version2Store=workspace://version2Store
|
|||||||
# if upgrading from a version that used unordered sequences in a cluster.
|
# if upgrading from a version that used unordered sequences in a cluster.
|
||||||
version.store.versionComparatorClass=
|
version.store.versionComparatorClass=
|
||||||
|
|
||||||
|
# Optional to set the child association index when creating a new version.
|
||||||
|
# This helps ordering versions when sequential IDs are not guaranteed by the DBMS.
|
||||||
|
# Not compatible with AGS < 7.1.1
|
||||||
|
# Once enabled, it should not be disabled again or new versions will go back
|
||||||
|
# to have index -1 and you will get the wrong order in version history.
|
||||||
|
# Please, see MNT-22715 for details.
|
||||||
|
version.store.useVersionAssocIndex=false
|
||||||
|
|
||||||
# Folders for storing people
|
# Folders for storing people
|
||||||
system.system_container.childname=sys:system
|
system.system_container.childname=sys:system
|
||||||
system.people_container.childname=sys:people
|
system.people_container.childname=sys:people
|
||||||
@@ -1308,3 +1316,6 @@ system.tempFileCleaner.maxTimeToRun=
|
|||||||
|
|
||||||
# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table
|
# Property to long running migration to remove alf_server in v7+ patch.db-V7.1.0-remove-alf_server-table
|
||||||
system.remove-alf_server-table-from-db.ignored=true
|
system.remove-alf_server-table-from-db.ignored=true
|
||||||
|
|
||||||
|
# pre-configured allow list of media/mime types to allow inline instead of attachment (via Content-Disposition response header)
|
||||||
|
content.nonAttach.mimetypes=application/pdf,image/jpeg,image/gif,image/png,image/tiff,image/bmp
|
||||||
|
@@ -209,6 +209,7 @@ import org.junit.runners.Suite;
|
|||||||
org.alfresco.repo.security.authentication.AuthorizationTest.class,
|
org.alfresco.repo.security.authentication.AuthorizationTest.class,
|
||||||
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
|
org.alfresco.repo.security.permissions.PermissionCheckedCollectionTest.class,
|
||||||
org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSetTest.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.ChainingAuthenticationServiceTest.class,
|
||||||
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
|
org.alfresco.repo.security.authentication.NameBasedUserNameGeneratorTest.class,
|
||||||
org.alfresco.repo.version.common.VersionImplTest.class,
|
org.alfresco.repo.version.common.VersionImplTest.class,
|
||||||
|
@@ -31,17 +31,18 @@ import java.io.PrintWriter;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.dictionary.DictionaryDAO;
|
import org.alfresco.repo.dictionary.DictionaryDAO;
|
||||||
import org.alfresco.repo.dictionary.NamespaceDAO;
|
import org.alfresco.repo.dictionary.NamespaceDAO;
|
||||||
|
import org.alfresco.repo.i18n.MessageService;
|
||||||
import org.alfresco.repo.node.db.DbNodeServiceImpl;
|
import org.alfresco.repo.node.db.DbNodeServiceImpl;
|
||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
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.admin.RepoAdminService;
|
||||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
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.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
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.junit.experimental.categories.Category;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RepoAdminServiceImpl
|
* @see RepoAdminServiceImpl
|
||||||
*
|
*
|
||||||
@@ -88,6 +92,7 @@ public class RepoAdminServiceImplTest extends TestCase
|
|||||||
private NamespaceService namespaceService;
|
private NamespaceService namespaceService;
|
||||||
private BehaviourFilter behaviourFilter;
|
private BehaviourFilter behaviourFilter;
|
||||||
private DictionaryDAO dictionaryDAO;
|
private DictionaryDAO dictionaryDAO;
|
||||||
|
private MessageService messageService;
|
||||||
|
|
||||||
final String modelPrefix = "model-";
|
final String modelPrefix = "model-";
|
||||||
final static String MKR = "{MKR}";
|
final static String MKR = "{MKR}";
|
||||||
@@ -140,6 +145,7 @@ public class RepoAdminServiceImplTest extends TestCase
|
|||||||
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
|
namespaceService = (NamespaceService) ctx.getBean("NamespaceService");
|
||||||
behaviourFilter = (BehaviourFilter)ctx.getBean("policyBehaviourFilter");
|
behaviourFilter = (BehaviourFilter)ctx.getBean("policyBehaviourFilter");
|
||||||
dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO");
|
dictionaryDAO = (DictionaryDAO) ctx.getBean("dictionaryDAO");
|
||||||
|
messageService = (MessageService) ctx.getBean("MessageService");
|
||||||
|
|
||||||
DbNodeServiceImpl dbNodeService = (DbNodeServiceImpl)ctx.getBean("dbNodeService");
|
DbNodeServiceImpl dbNodeService = (DbNodeServiceImpl)ctx.getBean("dbNodeService");
|
||||||
dbNodeService.setEnableTimestampPropagation(false);
|
dbNodeService.setEnableTimestampPropagation(false);
|
||||||
@@ -865,8 +871,182 @@ public class RepoAdminServiceImplTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Test deploy bundle from classpath
|
||||||
// TODO - Test custom message management
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,9 +25,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.dictionary;
|
package org.alfresco.repo.dictionary;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
@@ -53,8 +58,6 @@ import org.junit.After;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.experimental.categories.Category;
|
import org.junit.experimental.categories.Category;
|
||||||
|
|
||||||
import javax.transaction.UserTransaction;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Category(BaseSpringTestsCategory.class)
|
@Category(BaseSpringTestsCategory.class)
|
||||||
@@ -94,6 +97,14 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
|
|
||||||
"</model>";
|
"</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 */
|
/** Behaviour filter */
|
||||||
private BehaviourFilter behaviourFilter;
|
private BehaviourFilter behaviourFilter;
|
||||||
|
|
||||||
@@ -123,7 +134,8 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
|
|
||||||
private UserTransaction txn;
|
private UserTransaction txn;
|
||||||
private StoreRef storeRef;
|
private StoreRef storeRef;
|
||||||
private NodeRef rootNodeRef;
|
private NodeRef rootModelsNodeRef;
|
||||||
|
private NodeRef rootMessagesNodeRef;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception
|
public void before() throws Exception
|
||||||
@@ -151,7 +163,17 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
|
|
||||||
// Create the store and get the root node
|
// Create the store and get the root node
|
||||||
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
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();
|
txn.commit();
|
||||||
|
|
||||||
@@ -167,18 +189,20 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
this.bootstrap.setNamespaceService(this.namespaceService);
|
this.bootstrap.setNamespaceService(this.namespaceService);
|
||||||
this.bootstrap.setMessageService(this.messageService);
|
this.bootstrap.setMessageService(this.messageService);
|
||||||
this.bootstrap.setPolicyComponent(this.policyComponent);
|
this.bootstrap.setPolicyComponent(this.policyComponent);
|
||||||
|
|
||||||
RepositoryLocation location = new RepositoryLocation();
|
RepositoryLocation modelsLocation = new RepositoryLocation(this.storeRef,
|
||||||
location.setStoreProtocol(this.storeRef.getProtocol());
|
this.nodeService.getPath(rootModelsNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
|
||||||
location.setStoreId(this.storeRef.getIdentifier());
|
RepositoryLocation messagesLocation = new RepositoryLocation(this.storeRef,
|
||||||
location.setQueryLanguage(RepositoryLocation.LANGUAGE_PATH);
|
this.nodeService.getPath(rootMessagesNodeRef).toPrefixString(namespaceService), RepositoryLocation.LANGUAGE_PATH);
|
||||||
// NOTE: we are not setting the path for now .. in doing so we are searching the root node only
|
|
||||||
|
List<RepositoryLocation> modelsLocations = new ArrayList<RepositoryLocation>();
|
||||||
List<RepositoryLocation> locations = new ArrayList<RepositoryLocation>();
|
modelsLocations.add(modelsLocation);
|
||||||
locations.add(location);
|
List<RepositoryLocation> messagesLocations = new ArrayList<RepositoryLocation>();
|
||||||
|
messagesLocations.add(messagesLocation);
|
||||||
this.bootstrap.setRepositoryModelsLocations(locations);
|
|
||||||
|
this.bootstrap.setRepositoryModelsLocations(modelsLocations);
|
||||||
|
this.bootstrap.setRepositoryMessagesLocations(messagesLocations);
|
||||||
|
|
||||||
// register with dictionary service
|
// register with dictionary service
|
||||||
this.bootstrap.register();
|
this.bootstrap.register();
|
||||||
txn.commit();
|
txn.commit();
|
||||||
@@ -224,7 +248,15 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
"Test model one",
|
"Test model one",
|
||||||
"base1",
|
"base1",
|
||||||
"prop1");
|
"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
|
// Check that the model is not in the dictionary yet
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -251,6 +283,12 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
QName.createQName("http://www.alfresco.org/model/test3DictionaryBootstrapFromRepo/1.0", "testModel3"));
|
QName.createQName("http://www.alfresco.org/model/test3DictionaryBootstrapFromRepo/1.0", "testModel3"));
|
||||||
assertNotNull(modelDefinition3);
|
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();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +315,7 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
{
|
{
|
||||||
// Create a model node
|
// Create a model node
|
||||||
NodeRef model = this.nodeService.createNode(
|
NodeRef model = this.nodeService.createNode(
|
||||||
this.rootNodeRef,
|
this.rootModelsNodeRef,
|
||||||
ContentModel.ASSOC_CHILDREN,
|
ContentModel.ASSOC_CHILDREN,
|
||||||
QName.createQName("{test}models"),
|
QName.createQName("{test}models"),
|
||||||
ContentModel.TYPE_DICTIONARY_MODEL).getChildRef();
|
ContentModel.TYPE_DICTIONARY_MODEL).getChildRef();
|
||||||
@@ -300,6 +338,39 @@ public class DictionaryRepositoryBootstrapTest extends BaseSpringTest
|
|||||||
return model;
|
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
|
* Gets the model string
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -25,7 +25,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.rendition2;
|
package org.alfresco.repo.rendition2;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import static java.lang.Thread.sleep;
|
||||||
|
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||||
|
import static org.alfresco.model.RenditionModel.PROP_RENDITION_CONTENT_HASH_CODE;
|
||||||
|
import static org.alfresco.repo.content.MimetypeMap.EXTENSION_BINARY;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.content.metadata.AsynchronousExtractor;
|
import org.alfresco.repo.content.metadata.AsynchronousExtractor;
|
||||||
@@ -60,15 +69,7 @@ import org.quartz.CronExpression;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import junit.framework.AssertionFailedError;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static java.lang.Thread.sleep;
|
|
||||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
|
||||||
import static org.alfresco.repo.content.MimetypeMap.EXTENSION_BINARY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class unites common utility methods for {@link org.alfresco.repo.rendition2} package tests.
|
* Class unites common utility methods for {@link org.alfresco.repo.rendition2} package tests.
|
||||||
@@ -531,4 +532,41 @@ public abstract class AbstractRenditionIntegrationTest extends BaseSpringTest
|
|||||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||||
txnHelper.doInTransaction(createUserCallback);
|
txnHelper.doInTransaction(createUserCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to check if the supplied content hash code is valid or not
|
||||||
|
*
|
||||||
|
* @param contentHashCode
|
||||||
|
* the hash code to verify
|
||||||
|
*
|
||||||
|
* @return true in case it is an actual hash code, false otherwise
|
||||||
|
*/
|
||||||
|
protected boolean isValidRenditionContentHashCode(int contentHashCode)
|
||||||
|
{
|
||||||
|
return contentHashCode != RenditionService2Impl.RENDITION2_DOES_NOT_EXIST
|
||||||
|
&& contentHashCode != RenditionService2Impl.SOURCE_HAS_NO_CONTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method which gets the content hash code from the supplied rendition node without specific validations (the
|
||||||
|
* equivalent method from {@link RenditionService2Impl} is not exposed)
|
||||||
|
*
|
||||||
|
* @param renditionNodeRef
|
||||||
|
* the rendition node
|
||||||
|
*
|
||||||
|
* @return -1 in case of there is no content, -2 in case rendition doesn't exist, the actual content hash code
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
protected int getRenditionContentHashCode(NodeRef renditionNodeRef)
|
||||||
|
{
|
||||||
|
int renditionContentHashCode = RenditionService2Impl.RENDITION2_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
if (renditionNodeRef != null)
|
||||||
|
{
|
||||||
|
Serializable hashCode = nodeService.getProperty(renditionNodeRef, PROP_RENDITION_CONTENT_HASH_CODE);
|
||||||
|
renditionContentHashCode = hashCode == null ? RenditionService2Impl.SOURCE_HAS_NO_CONTENT : (int) hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renditionContentHashCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -25,6 +25,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.rendition2;
|
package org.alfresco.repo.rendition2;
|
||||||
|
|
||||||
|
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.RenditionModel;
|
import org.alfresco.model.RenditionModel;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
@@ -36,16 +41,9 @@ import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
|||||||
import org.alfresco.service.cmr.security.PermissionService;
|
import org.alfresco.service.cmr.security.PermissionService;
|
||||||
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.junit.AfterClass;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.alfresco.model.ContentModel.PROP_CONTENT;
|
|
||||||
import static org.junit.Assert.assertNotEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for {@link RenditionService2}
|
* Integration tests for {@link RenditionService2}
|
||||||
*/
|
*/
|
||||||
@@ -308,6 +306,99 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
|||||||
assertTrue("The rendition should be generated by new Rendition Service", hasRenditionedAspect);
|
assertTrue("The rendition should be generated by new Rendition Service", hasRenditionedAspect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests new {@link RenditionService2Impl#clearRenditionContentData(NodeRef, String)} method.
|
||||||
|
* <p>
|
||||||
|
* This method cleans a rendition content and content hash code.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testClearRenditionContentData()
|
||||||
|
{
|
||||||
|
// Create a node
|
||||||
|
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||||
|
|
||||||
|
// Trigger the rendition
|
||||||
|
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||||
|
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||||
|
assertNotNull("Rendition was not generated", renditionNodeRef);
|
||||||
|
assertNotNull("Rendition was not generated", nodeService.getProperty(renditionNodeRef, ContentModel.PROP_CONTENT));
|
||||||
|
|
||||||
|
// Check the rendition content hash code is valid
|
||||||
|
int contentHashCode = getRenditionContentHashCode(renditionNodeRef);
|
||||||
|
assertTrue("Rendition content hash code was not generated", isValidRenditionContentHashCode(contentHashCode));
|
||||||
|
|
||||||
|
// Disable renditionService2
|
||||||
|
renditionService2.setEnabled(false);
|
||||||
|
|
||||||
|
// Call 'clearRenditionContentData' method directly to prove rendition content will be cleaned
|
||||||
|
AuthenticationUtil.runAs((AuthenticationUtil.RunAsWork<Void>) () ->
|
||||||
|
transactionService.getRetryingTransactionHelper().doInTransaction(() ->
|
||||||
|
{
|
||||||
|
renditionService2.clearRenditionContentData(sourceNodeRef, DOC_LIB);
|
||||||
|
return null;
|
||||||
|
}), ADMIN);
|
||||||
|
|
||||||
|
// The rendition should not have content by now
|
||||||
|
assertNull("Rendition has content", nodeService.getProperty(renditionNodeRef, ContentModel.PROP_CONTENT));
|
||||||
|
|
||||||
|
// The rendition should not have a content hash code by now
|
||||||
|
contentHashCode = getRenditionContentHashCode(renditionNodeRef);
|
||||||
|
assertFalse("Rendition has content hash code", isValidRenditionContentHashCode(contentHashCode));
|
||||||
|
|
||||||
|
// Enable renditionService2
|
||||||
|
renditionService2.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a rendition without content (but with contentHashCode) can be generated again.
|
||||||
|
* <p>
|
||||||
|
* If the rendition consumption receives a null InputStream, the contentHashCode should be cleaned from the
|
||||||
|
* rendition node, allowing new requests to generate the rendition.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRenditionWithoutContentButWithContentHashCode()
|
||||||
|
{
|
||||||
|
// Create a node with an actual rendition
|
||||||
|
NodeRef sourceNodeRef = createSource(ADMIN, "quick.jpg");
|
||||||
|
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||||
|
NodeRef renditionNodeRef = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||||
|
assertNotNull("Rendition was not generated", renditionNodeRef);
|
||||||
|
assertNotNull("Rendition was not generated", nodeService.getProperty(renditionNodeRef, ContentModel.PROP_CONTENT));
|
||||||
|
|
||||||
|
// Clear rendition content (at this point we're forcing a rendition without content but with hash code)
|
||||||
|
clearContent(ADMIN, renditionNodeRef);
|
||||||
|
assertNull("Rendition has content", nodeService.getProperty(renditionNodeRef, ContentModel.PROP_CONTENT));
|
||||||
|
|
||||||
|
// Check that rendition still has the content hash code
|
||||||
|
final int contentHashCode = getRenditionContentHashCode(renditionNodeRef);
|
||||||
|
assertTrue("Rendition content hash code was not generated", isValidRenditionContentHashCode(contentHashCode));
|
||||||
|
|
||||||
|
// Call the 'consume' method directly supplying a null InputStream
|
||||||
|
// This is explicitly called to prove that rendition hash code will be cleaned (as opposite to previous behavior)
|
||||||
|
RenditionDefinition2 renditionDefinition = renditionDefinitionRegistry2.getRenditionDefinition(DOC_LIB);
|
||||||
|
AuthenticationUtil.runAs(() -> {
|
||||||
|
renditionService2.consume(sourceNodeRef, null, renditionDefinition, contentHashCode);
|
||||||
|
return null;
|
||||||
|
}, ADMIN);
|
||||||
|
waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, false);
|
||||||
|
|
||||||
|
// The content hash code should have been cleaned from the rendition node
|
||||||
|
int contentHashCode2 = getRenditionContentHashCode(renditionNodeRef);
|
||||||
|
assertFalse("Rendition content hash code was not cleaned", isValidRenditionContentHashCode(contentHashCode2));
|
||||||
|
|
||||||
|
// Attempts to render the rendition again
|
||||||
|
render(ADMIN, sourceNodeRef, DOC_LIB);
|
||||||
|
NodeRef renditionNodeRef2 = waitForRendition(ADMIN, sourceNodeRef, DOC_LIB, true);
|
||||||
|
assertEquals("New rendition nodeRef is different", renditionNodeRef.toString(), renditionNodeRef2.toString());
|
||||||
|
assertNotNull("New rendition content was not generated", nodeService.getProperty(renditionNodeRef2, ContentModel.PROP_CONTENT));
|
||||||
|
|
||||||
|
// Check the new rendition content hash code
|
||||||
|
int contentHashCode3 = getRenditionContentHashCode(renditionNodeRef2);
|
||||||
|
assertTrue("New rendition content hash code was not generated", isValidRenditionContentHashCode(contentHashCode3));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated can be removed when we remove the original RenditionService
|
* @deprecated can be removed when we remove the original RenditionService
|
||||||
*/
|
*/
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2021 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* 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 systemNodeRef;
|
||||||
|
|
||||||
|
protected NodeRef abstainedNode;
|
||||||
|
|
||||||
protected AuthenticationComponent authenticationComponent;
|
protected AuthenticationComponent authenticationComponent;
|
||||||
|
|
||||||
protected ModelDAO permissionModelDAO;
|
protected ModelDAO permissionModelDAO;
|
||||||
@@ -186,6 +188,8 @@ public abstract class AbstractPermissionTest extends TestCase
|
|||||||
props = createPersonProperties(USER2_LEMUR);
|
props = createPersonProperties(USER2_LEMUR);
|
||||||
nodeService.createNode(typesNodeRef, children, ContentModel.TYPE_PERSON, container, props).getChildRef();
|
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
|
// create an authentication object e.g. the user
|
||||||
if(authenticationDAO.userExists(USER1_ANDY))
|
if(authenticationDAO.userExists(USER1_ANDY))
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -39,7 +39,6 @@ import java.util.Properties;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
import junit.framework.AssertionFailedError;
|
|
||||||
|
|
||||||
import org.alfresco.model.ApplicationModel;
|
import org.alfresco.model.ApplicationModel;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
@@ -94,6 +93,8 @@ import org.springframework.test.annotation.Commit;
|
|||||||
import org.springframework.test.context.transaction.TestTransaction;
|
import org.springframework.test.context.transaction.TestTransaction;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* versionService test class.
|
* versionService test class.
|
||||||
*
|
*
|
||||||
@@ -575,6 +576,86 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When IDs are out of order the comparator only fixes the order we retrieve versions. Any operation fails due to
|
||||||
|
* the head version not being the latest. (MNT-22715)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testVersionIndex()
|
||||||
|
{
|
||||||
|
setUseVersionAssocIndex(true);
|
||||||
|
NodeRef versionableNode = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName("{test}MyVersionableNodeTestIndex"), ContentModel.TYPE_CONTENT, null).getChildRef();
|
||||||
|
nodeService.addAspect(versionableNode, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||||
|
Version version1 = createVersion(versionableNode);
|
||||||
|
Version version2 = createVersion(versionableNode);
|
||||||
|
Version version3 = createVersion(versionableNode);
|
||||||
|
|
||||||
|
VersionHistory vh = versionService.getVersionHistory(versionableNode);
|
||||||
|
assertEquals("Version History does not contain 3 versions", 3, vh.getAllVersions().size());
|
||||||
|
|
||||||
|
NodeRef root = nodeService.getPrimaryParent(vh.getRootVersion().getFrozenStateNodeRef()).getParentRef();
|
||||||
|
NodeRef versionHistoryNode = dbNodeService.getChildByName(root, Version2Model.CHILD_QNAME_VERSION_HISTORIES,
|
||||||
|
versionableNode.getId());
|
||||||
|
|
||||||
|
// getChildAssocs orders by assoc_index first and then by ID. Version History relies on this.
|
||||||
|
List<ChildAssociationRef> vhChildAssocs = nodeService.getChildAssocs(versionHistoryNode);
|
||||||
|
int index = 0;
|
||||||
|
for (ChildAssociationRef vhChildAssoc : vhChildAssocs)
|
||||||
|
{
|
||||||
|
// Unset indexes are -1
|
||||||
|
assertFalse("Index is not set", vhChildAssoc.getNthSibling() < 0);
|
||||||
|
assertTrue("Index is not increasing as expected", vhChildAssoc.getNthSibling() > index);
|
||||||
|
index = vhChildAssoc.getNthSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("1st version is not 1st assoc", version1.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(0).getChildRef().getId());
|
||||||
|
assertEquals("2nd version is not 2nd assoc", version2.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(1).getChildRef().getId());
|
||||||
|
assertEquals("3rd version is not 3rd assoc", version3.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(2).getChildRef().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test version assoc index use disabled
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testVersionIndexDisabled()
|
||||||
|
{
|
||||||
|
setUseVersionAssocIndex(false);
|
||||||
|
NodeRef versionableNode = nodeService
|
||||||
|
.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN,
|
||||||
|
QName.createQName("{test}MyVersionableNodeTestWithoutIndex"), ContentModel.TYPE_CONTENT, null)
|
||||||
|
.getChildRef();
|
||||||
|
nodeService.addAspect(versionableNode, ContentModel.ASPECT_VERSIONABLE, new HashMap<QName, Serializable>());
|
||||||
|
Version version1 = createVersion(versionableNode);
|
||||||
|
Version version2 = createVersion(versionableNode);
|
||||||
|
Version version3 = createVersion(versionableNode);
|
||||||
|
|
||||||
|
VersionHistory vh = versionService.getVersionHistory(versionableNode);
|
||||||
|
assertEquals("Version History does not contain 3 versions", 3, vh.getAllVersions().size());
|
||||||
|
|
||||||
|
NodeRef root = nodeService.getPrimaryParent(vh.getRootVersion().getFrozenStateNodeRef()).getParentRef();
|
||||||
|
NodeRef versionHistoryNode = dbNodeService.getChildByName(root, Version2Model.CHILD_QNAME_VERSION_HISTORIES,
|
||||||
|
versionableNode.getId());
|
||||||
|
|
||||||
|
// getChildAssocs orders by assoc_index first and then by ID. Version History relies on this.
|
||||||
|
List<ChildAssociationRef> vhChildAssocs = nodeService.getChildAssocs(versionHistoryNode);
|
||||||
|
for (ChildAssociationRef vhChildAssoc : vhChildAssocs)
|
||||||
|
{
|
||||||
|
// Unset indexes are -1
|
||||||
|
assertTrue("Index is not set", vhChildAssoc.getNthSibling() < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("1st version is not 1st assoc", version1.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(0).getChildRef().getId());
|
||||||
|
assertEquals("2nd version is not 2nd assoc", version2.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(1).getChildRef().getId());
|
||||||
|
assertEquals("3rd version is not 3rd assoc", version3.getFrozenStateNodeRef().getId(),
|
||||||
|
vhChildAssocs.get(2).getChildRef().getId());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the versionService to be one that has is db ids out of order
|
* Sets the versionService to be one that has is db ids out of order
|
||||||
* so would normally have versions displayed in the wrong order.
|
* so would normally have versions displayed in the wrong order.
|
||||||
@@ -612,6 +693,25 @@ public class VersionServiceImplTest extends BaseVersionStoreTest
|
|||||||
setVersionService(versionService);
|
setVersionService(versionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the versionService to use the version assoc Index
|
||||||
|
* @param useVersionAssocIndex
|
||||||
|
*/
|
||||||
|
private void setUseVersionAssocIndex(boolean useVersionAssocIndex)
|
||||||
|
{
|
||||||
|
Version2ServiceImpl versionService = new Version2ServiceImpl();
|
||||||
|
versionService.setNodeService(nodeService);
|
||||||
|
versionService.setDbNodeService(dbNodeService); // mtAwareNodeService
|
||||||
|
versionService.setSearcher(versionSearchService);
|
||||||
|
versionService.setDictionaryService(dictionaryService);
|
||||||
|
versionService.setPolicyComponent(policyComponent);
|
||||||
|
versionService.setPolicyBehaviourFilter(policyBehaviourFilter);
|
||||||
|
versionService.setPermissionService(permissionService);
|
||||||
|
versionService.setUseVersionAssocIndex(useVersionAssocIndex);
|
||||||
|
versionService.initialise();
|
||||||
|
setVersionService(versionService);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds another version to the version history then checks that getVersionHistory is returning
|
* Adds another version to the version history then checks that getVersionHistory is returning
|
||||||
* the correct data.
|
* the correct data.
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
mycustommessages.key1=This is a custom message
|
@@ -0,0 +1 @@
|
|||||||
|
mycustommessages.key1=Dies ist eine benutzerdefinierte Nachricht
|
@@ -0,0 +1 @@
|
|||||||
|
mycustommessages.key1=Ceci est un message personnalis\u00e9
|
Reference in New Issue
Block a user