mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-11-05 15:32:21 +00:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eca25addff | ||
|
|
0ea417ed37 | ||
|
|
fb811cdb2d | ||
|
|
9c0ac89015 | ||
|
|
1028b5c44b | ||
|
|
39d209a6a1 | ||
|
|
d9adbd60e1 | ||
|
|
cb07b26653 | ||
|
|
327129f021 | ||
|
|
afbaf11ff9 | ||
|
|
e779057f23 | ||
|
|
49ee9f8f29 | ||
|
|
213886cedd | ||
|
|
1be9a43bcd | ||
|
|
eceb7c0eb3 | ||
|
|
8cd46d4585 | ||
|
|
11d71e1941 | ||
|
|
353d50a35c | ||
|
|
2daafc711d | ||
|
|
dfa94fbe21 | ||
|
|
4a93aec66b | ||
|
|
3f0bbc9844 | ||
|
|
cb9ad42101 | ||
|
|
ca385b3bbc | ||
|
|
19c1582f1e | ||
|
|
06a918b082 | ||
|
|
f543de9959 | ||
|
|
8124279e6a | ||
|
|
4281fd5b2d | ||
|
|
d10d88306b | ||
|
|
1d7a37cd8c | ||
|
|
4bcb795452 | ||
|
|
393b064918 | ||
|
|
f741f2ca45 | ||
|
|
ef676f11e4 | ||
|
|
478c81fee3 | ||
|
|
cf9cc8042d | ||
|
|
8d790ed1cb | ||
|
|
87c7bd2877 | ||
|
|
9125f889b0 | ||
|
|
2fb74d2691 | ||
|
|
d671162dae | ||
|
|
bfaa629da7 | ||
|
|
719d73a558 | ||
|
|
a2aa867f3f | ||
|
|
8d745c536a | ||
|
|
b0f4c21ae3 | ||
|
|
72494e34fa | ||
|
|
792b7024ea | ||
|
|
40a1371f0d | ||
|
|
c22c47e63f | ||
|
|
232299d42d | ||
|
|
aca7969849 | ||
|
|
4ab2bbd3d6 | ||
|
|
f68f02372d | ||
|
|
9b0eedc8c1 | ||
|
|
f164dedcee | ||
|
|
9cdaa0a265 | ||
|
|
ef034e596b | ||
|
|
1251081a69 | ||
|
|
2d16eb6f42 | ||
|
|
e577134875 | ||
|
|
510eadd565 | ||
|
|
187646895c | ||
|
|
f9515e336f | ||
|
|
828dd20576 | ||
|
|
3372e20c35 | ||
|
|
64b5cace27 | ||
|
|
83acf26cf4 | ||
|
|
b3be0f2b7f | ||
|
|
7a6ebb9a05 | ||
|
|
fa0f239618 | ||
|
|
43799408a8 | ||
|
|
e7305006f0 | ||
|
|
40c30411af | ||
|
|
91f8b43237 | ||
|
|
6fccf828e1 | ||
|
|
3fac3373c9 | ||
|
|
ee857ce1de | ||
|
|
483d7fab21 | ||
|
|
590209b299 | ||
|
|
376514df67 | ||
|
|
7144a2dd94 | ||
|
|
b4da3d8c20 | ||
|
|
62de9ff0c0 | ||
|
|
a11acce720 | ||
|
|
1128011e15 | ||
|
|
d0cb45de0d | ||
|
|
2b48195896 | ||
|
|
fbb95d6a7f | ||
|
|
502427e852 | ||
|
|
3ff2d79641 | ||
|
|
f274b88ece | ||
|
|
21550ec30b | ||
|
|
8665267225 | ||
|
|
984b0bc719 | ||
|
|
5b89fc0be7 | ||
|
|
bf3a3382fd | ||
|
|
14d007fae8 | ||
|
|
79317ddc9d | ||
|
|
c0e762fe5e |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -107,7 +107,7 @@ jobs:
|
|||||||
bash ./scripts/ci/init.sh
|
bash ./scripts/ci/init.sh
|
||||||
bash ./scripts/ci/build.sh
|
bash ./scripts/ci/build.sh
|
||||||
- name: "Run SAST Scan"
|
- name: "Run SAST Scan"
|
||||||
uses: veracode/Veracode-pipeline-scan-action@v1.0.16
|
uses: veracode/Veracode-pipeline-scan-action@v1.0.20
|
||||||
with:
|
with:
|
||||||
vid: ${{ secrets.VERACODE_API_ID }}
|
vid: ${{ secrets.VERACODE_API_ID }}
|
||||||
vkey: ${{ secrets.VERACODE_API_KEY }}
|
vkey: ${{ secrets.VERACODE_API_KEY }}
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import com.github.dockerjava.netty.NettyDockerCmdExecFactory;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.alfresco.utility.Utility;
|
import org.alfresco.utility.Utility;
|
||||||
import org.apache.commons.lang.SystemUtils;
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
|||||||
import org.alfresco.rest.v0.RecordsAPI;
|
import org.alfresco.rest.v0.RecordsAPI;
|
||||||
import org.alfresco.rest.v0.RecordCategoriesAPI;
|
import org.alfresco.rest.v0.RecordCategoriesAPI;
|
||||||
import org.alfresco.test.AlfrescoTest;
|
import org.alfresco.test.AlfrescoTest;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import org.alfresco.rest.v0.service.DispositionScheduleService;
|
|||||||
import org.alfresco.test.AlfrescoTest;
|
import org.alfresco.test.AlfrescoTest;
|
||||||
import org.alfresco.utility.model.RepoTestModel;
|
import org.alfresco.utility.model.RepoTestModel;
|
||||||
import org.alfresco.utility.model.UserModel;
|
import org.alfresco.utility.model.UserModel;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
SOLR6_TAG=2.0.13
|
SOLR6_TAG=2.0.17
|
||||||
POSTGRES_TAG=15.4
|
POSTGRES_TAG=15.4
|
||||||
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
||||||
|
|||||||
@@ -15,6 +15,13 @@
|
|||||||
<parameter property="end" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<parameter property="end" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
</parameterMap>
|
</parameterMap>
|
||||||
|
|
||||||
|
<parameterMap id="parameter_NodeIdsWhichReferenceContentUrl" type="map">
|
||||||
|
<parameter property="contentUrlShort" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<parameter property="contentUrlCrc" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<parameter property="localName" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<parameter property="uri" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
</parameterMap>
|
||||||
|
|
||||||
<resultMap id="result_NodeRefEntity" type="org.alfresco.module.org_alfresco_module_rm.query.NodeRefEntity">
|
<resultMap id="result_NodeRefEntity" type="org.alfresco.module.org_alfresco_module_rm.query.NodeRefEntity">
|
||||||
<result property="row" column="row" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="row" column="row" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="protocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
<result property="protocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
@@ -55,18 +62,21 @@
|
|||||||
|
|
||||||
<!-- Get list of node ids which reference given content url -->
|
<!-- Get list of node ids which reference given content url -->
|
||||||
<select id="select_NodeIdsWhichReferenceContentUrl"
|
<select id="select_NodeIdsWhichReferenceContentUrl"
|
||||||
parameterType="ContentUrl"
|
parameterMap="parameter_NodeIdsWhichReferenceContentUrl"
|
||||||
resultMap="result_NodeIds">
|
resultMap="result_NodeIds">
|
||||||
select
|
select
|
||||||
p.node_id
|
p.node_id
|
||||||
from
|
from
|
||||||
alf_content_url cu
|
alf_content_url cu
|
||||||
LEFT OUTER JOIN alf_content_data cd ON (cd.content_url_id = cu.id)
|
left outer join alf_content_data cd ON (cd.content_url_id = cu.id)
|
||||||
LEFT OUTER JOIN alf_node_properties p ON (p.long_value = cd.id)
|
left outer join alf_node_properties p ON (p.long_value = cd.id)
|
||||||
WHERE
|
left outer join alf_qname q ON (q.id = p.qname_id)
|
||||||
content_url_short = #{contentUrlShort} and
|
left outer join alf_namespace n ON (n.id = q.ns_id)
|
||||||
content_url_crc = #{contentUrlCrc}
|
where
|
||||||
|
cu.content_url_short = ? and
|
||||||
|
cu.content_url_crc = ? and
|
||||||
|
q.local_name = ? and
|
||||||
|
n.uri = ?
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="select_RecordFoldersWithSchedules"
|
<select id="select_RecordFoldersWithSchedules"
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
package org.alfresco.module.org_alfresco_module_rm.query;
|
package org.alfresco.module.org_alfresco_module_rm.query;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -36,6 +35,11 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.mybatis.spring.SqlSessionTemplate;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||||
import org.alfresco.repo.domain.contentdata.ContentUrlEntity;
|
import org.alfresco.repo.domain.contentdata.ContentUrlEntity;
|
||||||
import org.alfresco.repo.domain.node.NodeDAO;
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
@@ -47,9 +51,6 @@ 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.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.mybatis.spring.SqlSessionTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records management query DAO implementation
|
* Records management query DAO implementation
|
||||||
@@ -89,7 +90,8 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
protected TenantService tenantService;
|
protected TenantService tenantService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sqlSessionTemplate SQL session template
|
* @param sqlSessionTemplate
|
||||||
|
* SQL session template
|
||||||
*/
|
*/
|
||||||
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
|
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
|
||||||
{
|
{
|
||||||
@@ -97,7 +99,8 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param qnameDAO qname DAO
|
* @param qnameDAO
|
||||||
|
* qname DAO
|
||||||
*/
|
*/
|
||||||
public final void setQnameDAO(QNameDAO qnameDAO)
|
public final void setQnameDAO(QNameDAO qnameDAO)
|
||||||
{
|
{
|
||||||
@@ -173,8 +176,9 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
/**
|
/**
|
||||||
* Get a set of node reference which reference the provided content URL
|
* Get a set of node reference which reference the provided content URL
|
||||||
*
|
*
|
||||||
* @param String contentUrl content URL
|
* @param String
|
||||||
* @return Set<NodeRef> set of nodes that reference the provided content URL
|
* contentUrl content URL
|
||||||
|
* @return Set<NodeRef> set of nodes that reference the provided content URL
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<NodeRef> getNodeRefsWhichReferenceContentUrl(String contentUrl)
|
public Set<NodeRef> getNodeRefsWhichReferenceContentUrl(String contentUrl)
|
||||||
@@ -188,13 +192,19 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
|
ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
|
||||||
contentUrlEntity.setContentUrl(contentUrl.toLowerCase());
|
contentUrlEntity.setContentUrl(contentUrl.toLowerCase());
|
||||||
|
|
||||||
|
Map<String, Object> params = new HashMap<>(4);
|
||||||
|
params.put("contentUrlShort", contentUrlEntity.getContentUrlShort());
|
||||||
|
params.put("contentUrlCrc", contentUrlEntity.getContentUrlCrc());
|
||||||
|
params.put("localName", ContentModel.PROP_CONTENT.getLocalName());
|
||||||
|
params.put("uri", ContentModel.PROP_CONTENT.getNamespaceURI());
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("Executing query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL);
|
logger.debug("Executing query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all the node ids which reference the given content url
|
// Get all the node ids which reference the given content url
|
||||||
List<Long> nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, contentUrlEntity);
|
List<Long> nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, params);
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
@@ -224,7 +234,7 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logMessage.append(nodeRefToAdd)
|
logMessage.append(nodeRefToAdd)
|
||||||
.append(" (from version)");
|
.append(" (from version)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +242,7 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodeRefToAdd = nodeDAO.getNodeIdStatus(nodeId)
|
nodeRefToAdd = nodeDAO.getNodeIdStatus(nodeId)
|
||||||
.getNodeRef();
|
.getNodeRef();
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logMessage.append(nodeRefToAdd);
|
logMessage.append(nodeRefToAdd);
|
||||||
@@ -266,9 +276,9 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
{
|
{
|
||||||
Map<String, Object> params = new HashMap<>(2);
|
Map<String, Object> params = new HashMap<>(2);
|
||||||
params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED)
|
params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED)
|
||||||
.getFirst());
|
.getFirst());
|
||||||
params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER)
|
params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER)
|
||||||
.getFirst());
|
.getFirst());
|
||||||
params.put("start", start);
|
params.put("start", start);
|
||||||
params.put("end", end);
|
params.put("end", end);
|
||||||
|
|
||||||
@@ -280,7 +290,7 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
for (NodeRefEntity nodeRefEntity : entities)
|
for (NodeRefEntity nodeRefEntity : entities)
|
||||||
{
|
{
|
||||||
results.add(
|
results.add(
|
||||||
new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid()));
|
new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
@@ -289,7 +299,8 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getPropertyStringValueEntity(String stringValue)
|
* @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getPropertyStringValueEntity(String stringValue)
|
||||||
*/
|
*/
|
||||||
public PropertyStringValueEntity getPropertyStringValueEntity(String stringValue){
|
public PropertyStringValueEntity getPropertyStringValueEntity(String stringValue)
|
||||||
|
{
|
||||||
|
|
||||||
PropertyStringValueEntity propertyStringValueEntity = new PropertyStringValueEntity();
|
PropertyStringValueEntity propertyStringValueEntity = new PropertyStringValueEntity();
|
||||||
propertyStringValueEntity.setValue(stringValue);
|
propertyStringValueEntity.setValue(stringValue);
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
import org.springframework.extensions.webscripts.ui.common.StringUtils;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.RenditionModel;
|
import org.alfresco.model.RenditionModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||||
@@ -43,7 +48,10 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
|
|||||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
import org.alfresco.query.PagingResults;
|
import org.alfresco.query.PagingResults;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
import org.alfresco.repo.security.authority.RMAuthority;
|
import org.alfresco.repo.security.authority.RMAuthority;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -55,12 +63,6 @@ import org.alfresco.service.namespace.RegexQNamePattern;
|
|||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
import org.springframework.context.ApplicationListener;
|
|
||||||
import org.springframework.context.event.ContextRefreshedEvent;
|
|
||||||
import org.springframework.extensions.webscripts.ui.common.StringUtils;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended security service implementation.
|
* Extended security service implementation.
|
||||||
@@ -69,9 +71,9 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
|
|||||||
* @since 2.1
|
* @since 2.1
|
||||||
*/
|
*/
|
||||||
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
||||||
implements ExtendedSecurityService,
|
implements ExtendedSecurityService,
|
||||||
RecordsManagementModel,
|
RecordsManagementModel,
|
||||||
ApplicationListener<ContextRefreshedEvent>
|
ApplicationListener<ContextRefreshedEvent>
|
||||||
{
|
{
|
||||||
/** ipr group names */
|
/** ipr group names */
|
||||||
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
|
static final String ROOT_IPR_GROUP = "INPLACE_RECORD_MANAGEMENT";
|
||||||
@@ -99,7 +101,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
private boolean enableUsernameNormalization;
|
private boolean enableUsernameNormalization;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param filePlanService file plan service
|
* @param filePlanService
|
||||||
|
* file plan service
|
||||||
*/
|
*/
|
||||||
public void setFilePlanService(FilePlanService filePlanService)
|
public void setFilePlanService(FilePlanService filePlanService)
|
||||||
{
|
{
|
||||||
@@ -107,7 +110,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param filePlanRoleService file plan role service
|
* @param filePlanRoleService
|
||||||
|
* file plan role service
|
||||||
*/
|
*/
|
||||||
public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService)
|
public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService)
|
||||||
{
|
{
|
||||||
@@ -115,7 +119,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param authorityService authority service
|
* @param authorityService
|
||||||
|
* authority service
|
||||||
*/
|
*/
|
||||||
public void setAuthorityService(AuthorityService authorityService)
|
public void setAuthorityService(AuthorityService authorityService)
|
||||||
{
|
{
|
||||||
@@ -123,7 +128,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param permissionService permission service
|
* @param permissionService
|
||||||
|
* permission service
|
||||||
*/
|
*/
|
||||||
public void setPermissionService(PermissionService permissionService)
|
public void setPermissionService(PermissionService permissionService)
|
||||||
{
|
{
|
||||||
@@ -131,7 +137,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param transactionService transaction service
|
* @param transactionService
|
||||||
|
* transaction service
|
||||||
*/
|
*/
|
||||||
public void setTransactionService(TransactionService transactionService)
|
public void setTransactionService(TransactionService transactionService)
|
||||||
{
|
{
|
||||||
@@ -154,19 +161,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
|
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent)
|
||||||
{
|
{
|
||||||
// run as System on bootstrap
|
// run as System on bootstrap
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Object>()
|
AuthenticationUtil.runAs(new RunAsWork<Object>() {
|
||||||
{
|
|
||||||
public Object doWork()
|
public Object doWork()
|
||||||
{
|
{
|
||||||
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>()
|
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
// if the root group doesn't exist then create it
|
// if the root group doesn't exist then create it
|
||||||
if (!authorityService.authorityExists(getRootIRPGroup()))
|
if (!authorityService.authorityExists(getRootIRPGroup()))
|
||||||
{
|
{
|
||||||
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP,
|
authorityService.createAuthority(AuthorityType.GROUP, ROOT_IPR_GROUP, ROOT_IPR_GROUP,
|
||||||
Collections.singleton(RMAuthority.ZONE_APP_RM));
|
Collections.singleton(RMAuthority.ZONE_APP_RM));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -186,7 +191,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
return GROUP_PREFIX + ROOT_IPR_GROUP;
|
return GROUP_PREFIX + ROOT_IPR_GROUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -236,8 +241,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Helper to get authorities for a given group
|
* Helper to get authorities for a given group
|
||||||
*
|
*
|
||||||
* @param group group name
|
* @param group
|
||||||
* @return Set<String> immediate authorities
|
* group name
|
||||||
|
* @return Set<String> immediate authorities
|
||||||
*/
|
*/
|
||||||
private Set<String> getAuthorities(String group)
|
private Set<String> getAuthorities(String group)
|
||||||
{
|
{
|
||||||
@@ -296,8 +302,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
* <p>
|
* <p>
|
||||||
* Return null if none found.
|
* Return null if none found.
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef
|
||||||
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
|
* node reference
|
||||||
|
* @return Pair<String, String> where first is the read group and second if the write group, null if none found
|
||||||
*/
|
*/
|
||||||
private Pair<String, String> getIPRGroups(NodeRef nodeRef)
|
private Pair<String, String> getIPRGroups(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
@@ -333,17 +340,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Given a set of readers and writers find or create the appropriate IPR groups.
|
* Given a set of readers and writers find or create the appropriate IPR groups.
|
||||||
* <p>
|
* <p>
|
||||||
* The IPR groups are named with hashes of the authority lists in order to reduce
|
* The IPR groups are named with hashes of the authority lists in order to reduce the set of groups that require exact match. A further index is used to handle a situation where there is a hash clash, but a difference in the authority lists.
|
||||||
* the set of groups that require exact match. A further index is used to handle
|
|
||||||
* a situation where there is a hash clash, but a difference in the authority lists.
|
|
||||||
* <p>
|
* <p>
|
||||||
* When no match is found the groups are created. Once created
|
* When no match is found the groups are created. Once created
|
||||||
*
|
*
|
||||||
* @param filePlan file plan
|
* @param filePlan
|
||||||
* @param readers authorities with read
|
* file plan
|
||||||
* @param writers authorities with write
|
* @param readers
|
||||||
* @return Pair<String, String> where first is the full name of the read group and
|
* authorities with read
|
||||||
* second is the full name of the write group
|
* @param writers
|
||||||
|
* authorities with write
|
||||||
|
* @return Pair<String, String> where first is the full name of the read group and second is the full name of the write group
|
||||||
*/
|
*/
|
||||||
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
|
private Pair<String, String> createOrFindIPRGroups(Set<String> readers, Set<String> writers)
|
||||||
{
|
{
|
||||||
@@ -355,20 +362,28 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Create or find an IPR group based on the provided prefix and authorities.
|
* Create or find an IPR group based on the provided prefix and authorities.
|
||||||
*
|
*
|
||||||
* @param groupPrefix group prefix
|
* @param groupPrefix
|
||||||
* @param authorities authorities
|
* group prefix
|
||||||
* @return String full group name
|
* @param authorities
|
||||||
|
* authorities
|
||||||
|
* @return String full group name
|
||||||
*/
|
*/
|
||||||
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
|
private String createOrFindIPRGroup(String groupPrefix, Set<String> authorities)
|
||||||
{
|
{
|
||||||
String group = null;
|
String group = null;
|
||||||
|
|
||||||
|
// If enabled, the authorities are forced to match the correct casing of the usernames in case they were set
|
||||||
|
// with the incorrect casing.
|
||||||
|
// If not, it will just use the authorities as they are.
|
||||||
|
// In normal circumstances, the authorities are in the correct casing, so this is disabled by default.
|
||||||
|
Set<String> authoritySet = normalizeAuthorities(authorities);
|
||||||
|
|
||||||
// find group or determine what the next index is if no group exists or there is a clash
|
// find group or determine what the next index is if no group exists or there is a clash
|
||||||
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities);
|
Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authoritySet);
|
||||||
|
|
||||||
if (groupResult.getFirst() == null)
|
if (groupResult.getFirst() == null)
|
||||||
{
|
{
|
||||||
group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond());
|
group = createIPRGroup(groupPrefix, authoritySet, groupResult.getSecond());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -381,13 +396,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Given a group name prefix and the authorities, finds the exact match existing group.
|
* Given a group name prefix and the authorities, finds the exact match existing group.
|
||||||
* <p>
|
* <p>
|
||||||
* If the group does not exist then the group returned is null and the index shows the next available
|
* If the group does not exist then the group returned is null and the index shows the next available group index for creation.
|
||||||
* group index for creation.
|
|
||||||
*
|
*
|
||||||
* @param groupPrefix group name prefix
|
* @param groupPrefix
|
||||||
* @param authorities authorities
|
* group name prefix
|
||||||
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second
|
* @param authorities
|
||||||
* if the next available create index
|
* authorities
|
||||||
|
* @return Pair<String, Integer> where first is the name of the found group, null if none found and second if the next available create index
|
||||||
*/
|
*/
|
||||||
private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities)
|
private Pair<String, Integer> findIPRGroup(String groupPrefix, Set<String> authorities)
|
||||||
{
|
{
|
||||||
@@ -396,13 +411,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
boolean hasMoreItems = true;
|
boolean hasMoreItems = true;
|
||||||
int pageCount = 0;
|
int pageCount = 0;
|
||||||
|
|
||||||
// If enabled, the authorities are forced to match the correct casing of the usernames in case they were set with the incorrect casing.
|
|
||||||
// If not, it will just use the authorities as they are.
|
|
||||||
// In normal circumstances, the authorities are in the correct casing, so this is disabled by default.
|
|
||||||
Set<String> authoritySet = normalizeAuthorities(authorities);
|
|
||||||
|
|
||||||
// determine the short name prefix
|
// determine the short name prefix
|
||||||
String groupShortNamePrefix = getIPRGroupPrefixShortName(groupPrefix, authoritySet);
|
String groupShortNamePrefix = getIPRGroupPrefixShortName(groupPrefix, authorities);
|
||||||
|
|
||||||
// iterate over the authorities to find a match
|
// iterate over the authorities to find a match
|
||||||
while (hasMoreItems == true)
|
while (hasMoreItems == true)
|
||||||
@@ -410,11 +420,11 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
// get matching authorities
|
// get matching authorities
|
||||||
PagingResults<String> results = authorityService.getAuthorities(
|
PagingResults<String> results = authorityService.getAuthorities(
|
||||||
AuthorityType.GROUP,
|
AuthorityType.GROUP,
|
||||||
RMAuthority.ZONE_APP_RM,
|
RMAuthority.ZONE_APP_RM,
|
||||||
groupShortNamePrefix,
|
groupShortNamePrefix,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
new PagingRequest(MAX_ITEMS*pageCount, MAX_ITEMS));
|
new PagingRequest(MAX_ITEMS * pageCount, MAX_ITEMS));
|
||||||
|
|
||||||
// record the total count
|
// record the total count
|
||||||
nextGroupIndex = nextGroupIndex + results.getPage().size();
|
nextGroupIndex = nextGroupIndex + results.getPage().size();
|
||||||
@@ -423,7 +433,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
for (String group : results.getPage())
|
for (String group : results.getPage())
|
||||||
{
|
{
|
||||||
// if exists and matches we have found our group
|
// if exists and matches we have found our group
|
||||||
if (isIPRGroupTrueMatch(group, authoritySet))
|
if (isIPRGroupTrueMatch(group, authorities))
|
||||||
{
|
{
|
||||||
return new Pair<String, Integer>(group, nextGroupIndex);
|
return new Pair<String, Integer>(group, nextGroupIndex);
|
||||||
}
|
}
|
||||||
@@ -431,7 +441,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
|
|
||||||
// determine if there are any more pages to inspect
|
// determine if there are any more pages to inspect
|
||||||
hasMoreItems = results.hasMoreItems();
|
hasMoreItems = results.hasMoreItems();
|
||||||
pageCount ++;
|
pageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pair<>(iprGroup, nextGroupIndex);
|
return new Pair<>(iprGroup, nextGroupIndex);
|
||||||
@@ -497,20 +507,22 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Determines whether a group exactly matches a list of authorities.
|
* Determines whether a group exactly matches a list of authorities.
|
||||||
*
|
*
|
||||||
* @param authorities list of authorities
|
* @param authorities
|
||||||
* @param group group
|
* list of authorities
|
||||||
|
* @param group
|
||||||
|
* group
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
|
private boolean isIPRGroupTrueMatch(String group, Set<String> authorities)
|
||||||
{
|
{
|
||||||
//Remove GROUP_EVERYONE for proper comparison as GROUP_EVERYONE is never included in an IPR group
|
// Remove GROUP_EVERYONE for proper comparison as GROUP_EVERYONE is never included in an IPR group
|
||||||
Set<String> plainAuthorities = new HashSet<String>();
|
Set<String> plainAuthorities = new HashSet<String>();
|
||||||
if (authorities != null)
|
if (authorities != null)
|
||||||
{
|
{
|
||||||
plainAuthorities.addAll(authorities);
|
plainAuthorities.addAll(authorities);
|
||||||
plainAuthorities.remove(PermissionService.ALL_AUTHORITIES);
|
plainAuthorities.remove(PermissionService.ALL_AUTHORITIES);
|
||||||
}
|
}
|
||||||
Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
|
Set<String> contained = authorityService.getContainedAuthorities(null, group, true);
|
||||||
return contained.equals(plainAuthorities);
|
return contained.equals(plainAuthorities);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,15 +531,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
* <p>
|
* <p>
|
||||||
* 'package' scope to help testing.
|
* 'package' scope to help testing.
|
||||||
*
|
*
|
||||||
* @param prefix prefix
|
* @param prefix
|
||||||
* @param authorities authorities
|
* prefix
|
||||||
* @return String group prefix short name
|
* @param authorities
|
||||||
|
* authorities
|
||||||
|
* @return String group prefix short name
|
||||||
*/
|
*/
|
||||||
/*package*/ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
|
/* package */ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder(128)
|
StringBuilder builder = new StringBuilder(128)
|
||||||
.append(prefix)
|
.append(prefix)
|
||||||
.append(getAuthoritySetHashCode(authorities));
|
.append(getAuthoritySetHashCode(authorities));
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
@@ -539,13 +553,17 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
* <p>
|
* <p>
|
||||||
* 'package' scope to help testing.
|
* 'package' scope to help testing.
|
||||||
*
|
*
|
||||||
* @param prefix prefix
|
* @param prefix
|
||||||
* @param readers read authorities
|
* prefix
|
||||||
* @param writers write authorities
|
* @param readers
|
||||||
* @param index group index
|
* read authorities
|
||||||
* @return String group short name
|
* @param writers
|
||||||
|
* write authorities
|
||||||
|
* @param index
|
||||||
|
* group index
|
||||||
|
* @return String group short name
|
||||||
*/
|
*/
|
||||||
/*package*/ String getIPRGroupShortName(String prefix, Set<String> authorities, int index)
|
/* package */ String getIPRGroupShortName(String prefix, Set<String> authorities, int index)
|
||||||
{
|
{
|
||||||
return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
|
return getIPRGroupShortName(prefix, authorities, Integer.toString(index));
|
||||||
}
|
}
|
||||||
@@ -555,17 +573,21 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
* <p>
|
* <p>
|
||||||
* Note this excludes the "GROUP_" prefix.
|
* Note this excludes the "GROUP_" prefix.
|
||||||
*
|
*
|
||||||
* @param prefix prefix
|
* @param prefix
|
||||||
* @param readers read authorities
|
* prefix
|
||||||
* @param writers write authorities
|
* @param readers
|
||||||
* @param index group index
|
* read authorities
|
||||||
* @return String group short name
|
* @param writers
|
||||||
|
* write authorities
|
||||||
|
* @param index
|
||||||
|
* group index
|
||||||
|
* @return String group short name
|
||||||
*/
|
*/
|
||||||
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
|
private String getIPRGroupShortName(String prefix, Set<String> authorities, String index)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder(128)
|
StringBuilder builder = new StringBuilder(128)
|
||||||
.append(getIPRGroupPrefixShortName(prefix, authorities))
|
.append(getIPRGroupPrefixShortName(prefix, authorities))
|
||||||
.append(index);
|
.append(index);
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
@@ -573,8 +595,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Gets the hashcode value of a set of authorities.
|
* Gets the hashcode value of a set of authorities.
|
||||||
*
|
*
|
||||||
* @param authorities set of authorities
|
* @param authorities
|
||||||
* @return int hash code
|
* set of authorities
|
||||||
|
* @return int hash code
|
||||||
*/
|
*/
|
||||||
private int getAuthoritySetHashCode(Set<String> authorities)
|
private int getAuthoritySetHashCode(Set<String> authorities)
|
||||||
{
|
{
|
||||||
@@ -589,10 +612,13 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Creates a new IPR group.
|
* Creates a new IPR group.
|
||||||
*
|
*
|
||||||
* @param groupNamePrefix group name prefix
|
* @param groupNamePrefix
|
||||||
* @param children child authorities
|
* group name prefix
|
||||||
* @param index group index
|
* @param children
|
||||||
* @return String full name of created group
|
* child authorities
|
||||||
|
* @param index
|
||||||
|
* group index
|
||||||
|
* @return String full name of created group
|
||||||
*/
|
*/
|
||||||
private String createIPRGroup(String groupNamePrefix, Set<String> children, int index)
|
private String createIPRGroup(String groupNamePrefix, Set<String> children, int index)
|
||||||
{
|
{
|
||||||
@@ -622,10 +648,10 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(DuplicateChildNodeNameException ex)
|
catch (DuplicateChildNodeNameException ex)
|
||||||
{
|
{
|
||||||
// the group was concurrently created
|
// Rethrow as ConcurrencyFailureException so that is can be retried and linked to the group created by the concurrent transaction
|
||||||
group = authorityService.getName(AuthorityType.GROUP, groupShortName);
|
throw new ConcurrencyFailureException("IPR group creation failed due to concurrent duplicate group name creation: " + groupShortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
@@ -634,8 +660,10 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Assign IPR groups to a node reference with the correct permissions.
|
* Assign IPR groups to a node reference with the correct permissions.
|
||||||
*
|
*
|
||||||
* @param iprGroups iprGroups, first read and second write
|
* @param iprGroups
|
||||||
* @param nodeRef node reference
|
* iprGroups, first read and second write
|
||||||
|
* @param nodeRef
|
||||||
|
* node reference
|
||||||
*/
|
*/
|
||||||
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
|
private void assignIPRGroupsToNode(Pair<String, String> iprGroups, NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
@@ -673,7 +701,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* Clear the nodes IPR permissions
|
* Clear the nodes IPR permissions
|
||||||
*
|
*
|
||||||
* @param nodeRef node reference
|
* @param nodeRef
|
||||||
|
* node reference
|
||||||
*/
|
*/
|
||||||
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
|
private void clearPermissions(NodeRef nodeRef, Pair<String, String> iprGroups)
|
||||||
{
|
{
|
||||||
@@ -685,7 +714,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public Set<String> getExtendedReaders(NodeRef nodeRef)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public Set<String> getExtendedReaders(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
return getReaders(nodeRef);
|
return getReaders(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -693,7 +724,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#getExtendedWriters(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public Set<String> getExtendedWriters(NodeRef nodeRef)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public Set<String> getExtendedWriters(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
return getWriters(nodeRef);
|
return getWriters(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -701,7 +734,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||||
{
|
{
|
||||||
set(nodeRef, readers, writers);
|
set(nodeRef, readers, writers);
|
||||||
}
|
}
|
||||||
@@ -709,7 +744,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#addExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void addExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||||
{
|
{
|
||||||
set(nodeRef, readers, writers);
|
set(nodeRef, readers, writers);
|
||||||
}
|
}
|
||||||
@@ -717,7 +754,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void removeAllExtendedSecurity(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
remove(nodeRef);
|
remove(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -725,7 +764,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers)
|
||||||
{
|
{
|
||||||
remove(nodeRef);
|
remove(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -733,7 +774,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, java.util.Set, boolean)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String>writers, boolean applyToParents)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void removeExtendedSecurity(NodeRef nodeRef, Set<String> readers, Set<String> writers, boolean applyToParents)
|
||||||
{
|
{
|
||||||
remove(nodeRef);
|
remove(nodeRef);
|
||||||
}
|
}
|
||||||
@@ -741,7 +784,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
|
|||||||
/**
|
/**
|
||||||
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
* @see org.alfresco.module.org_alfresco_module_rm.security.DeprecatedExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef, boolean)
|
||||||
*/
|
*/
|
||||||
@Override @Deprecated public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void removeAllExtendedSecurity(NodeRef nodeRef, boolean applyToParents)
|
||||||
{
|
{
|
||||||
remove(nodeRef);
|
remove(nodeRef);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,14 +29,23 @@ package org.alfresco.module.org_alfresco_module_rm.test.legacy.service;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.query.PagingResults;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
import org.alfresco.repo.site.SiteModel;
|
import org.alfresco.repo.site.SiteModel;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.security.AccessPermission;
|
||||||
import org.alfresco.service.cmr.security.AccessStatus;
|
import org.alfresco.service.cmr.security.AccessStatus;
|
||||||
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
import org.alfresco.service.cmr.site.SiteService;
|
import org.alfresco.service.cmr.site.SiteService;
|
||||||
import org.alfresco.service.cmr.site.SiteVisibility;
|
import org.alfresco.service.cmr.site.SiteVisibility;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
@@ -73,8 +82,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
private String createTestUser()
|
private String createTestUser()
|
||||||
{
|
{
|
||||||
return doTestInTransaction(new Test<String>()
|
return doTestInTransaction(new Test<String>() {
|
||||||
{
|
|
||||||
public String run()
|
public String run()
|
||||||
{
|
{
|
||||||
String userName = GUID.generate();
|
String userName = GUID.generate();
|
||||||
@@ -90,8 +98,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
final String elephant = createTestUser();
|
final String elephant = createTestUser();
|
||||||
final String snake = createTestUser();
|
final String snake = createTestUser();
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>() {
|
||||||
{
|
|
||||||
public Void run()
|
public Void run()
|
||||||
{
|
{
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(filePlan));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(filePlan));
|
||||||
@@ -118,7 +125,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
// test remove
|
// test remove
|
||||||
extendedSecurityService.remove(recordToo);
|
extendedSecurityService.remove(recordToo);
|
||||||
|
|
||||||
assertFalse(extendedSecurityService.hasExtendedSecurity(recordToo));
|
assertFalse(extendedSecurityService.hasExtendedSecurity(recordToo));
|
||||||
assertTrue(extendedSecurityService.getReaders(recordToo).isEmpty());
|
assertTrue(extendedSecurityService.getReaders(recordToo).isEmpty());
|
||||||
assertTrue(extendedSecurityService.getWriters(recordToo).isEmpty());
|
assertTrue(extendedSecurityService.getWriters(recordToo).isEmpty());
|
||||||
@@ -133,8 +140,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
final String monkey = createTestUser();
|
final String monkey = createTestUser();
|
||||||
final String elephant = createTestUser();
|
final String elephant = createTestUser();
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>() {
|
||||||
{
|
|
||||||
Set<String> extendedReaders = new HashSet<>(2);
|
Set<String> extendedReaders = new HashSet<>(2);
|
||||||
|
|
||||||
public Void run() throws Exception
|
public Void run() throws Exception
|
||||||
@@ -184,112 +190,337 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
|
|||||||
|
|
||||||
public void testDifferentUsersDifferentPermissions()
|
public void testDifferentUsersDifferentPermissions()
|
||||||
{
|
{
|
||||||
final String userNone = createTestUser();
|
final String userNone = createTestUser();
|
||||||
final String userRead = createTestUser();
|
final String userRead = createTestUser();
|
||||||
final String userWrite = createTestUser();
|
final String userWrite = createTestUser();
|
||||||
final String siteShortName = GUID.generate();
|
final String siteShortName = GUID.generate();
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>() {
|
||||||
{
|
|
||||||
public Void run() throws Exception
|
public Void run() throws Exception
|
||||||
{
|
{
|
||||||
siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE);
|
siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final NodeRef documentLibrary = doTestInTransaction(new Test<NodeRef>()
|
final NodeRef documentLibrary = doTestInTransaction(new Test<NodeRef>() {
|
||||||
{
|
|
||||||
public NodeRef run() throws Exception
|
public NodeRef run() throws Exception
|
||||||
{
|
{
|
||||||
siteService.setMembership(siteShortName, userRead, SiteModel.SITE_CONSUMER);
|
siteService.setMembership(siteShortName, userRead, SiteModel.SITE_CONSUMER);
|
||||||
siteService.setMembership(siteShortName, userWrite, SiteModel.SITE_COLLABORATOR);
|
siteService.setMembership(siteShortName, userWrite, SiteModel.SITE_COLLABORATOR);
|
||||||
return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null);
|
return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
final NodeRef record = doTestInTransaction(new Test<NodeRef>()
|
final NodeRef record = doTestInTransaction(new Test<NodeRef>() {
|
||||||
{
|
|
||||||
public NodeRef run() throws Exception
|
public NodeRef run() throws Exception
|
||||||
{
|
{
|
||||||
NodeRef record = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
|
NodeRef record = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_CONTENT)
|
||||||
recordService.createRecord(filePlan, record);
|
.getNodeRef();
|
||||||
return record;
|
recordService.createRecord(filePlan, record);
|
||||||
|
return record;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
doTestInTransaction(new Test<Void>()
|
doTestInTransaction(new Test<Void>() {
|
||||||
{
|
|
||||||
public Void run() throws Exception
|
public Void run() throws Exception
|
||||||
{
|
{
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userNone);
|
||||||
}, userNone);
|
|
||||||
|
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userRead);
|
||||||
}, userRead);
|
|
||||||
|
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userWrite);
|
||||||
}, userWrite);
|
|
||||||
|
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userNone);
|
||||||
}, userNone);
|
|
||||||
|
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.DENIED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userRead);
|
||||||
}, userRead);
|
|
||||||
|
|
||||||
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
AuthenticationUtil.runAs(new RunAsWork<Void>() {
|
||||||
{
|
public Void doWork() throws Exception
|
||||||
public Void doWork() throws Exception
|
{
|
||||||
{
|
// check permissions
|
||||||
// check permissions
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, READ_RECORDS));
|
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
|
||||||
assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(record, FILING));
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
}, userWrite);
|
||||||
}, userWrite);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testConcurrentSetWithRetry()
|
||||||
|
{
|
||||||
|
Set<String> extendedReaders = new HashSet<>(2);
|
||||||
|
Set<String> extendedWriters = new HashSet<>(2);
|
||||||
|
|
||||||
|
Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters);
|
||||||
|
|
||||||
|
// For each record created previously, spawn a thread to set extended security so we cause concurrency
|
||||||
|
// failure trying to create IPR groups with the same name
|
||||||
|
fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, true);
|
||||||
|
|
||||||
|
// Look for duplicated IPR groups and verify all documents have the same groups assigned
|
||||||
|
verifyCreatedGroups(documents, false);
|
||||||
|
|
||||||
|
AuthenticationUtil.clearCurrentSecurityContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConcurrentSetWithoutRetry()
|
||||||
|
{
|
||||||
|
Set<String> extendedReaders = new HashSet<>(2);
|
||||||
|
Set<String> extendedWriters = new HashSet<>(2);
|
||||||
|
|
||||||
|
Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters);
|
||||||
|
|
||||||
|
// For each record created previously, spawn a thread to set extended security so we cause concurrency
|
||||||
|
// failure trying to create IPR groups with the same name.
|
||||||
|
// Since there is no retry, we expect to get a ConcurrencyFailureException
|
||||||
|
Assert.assertThrows(ConcurrencyFailureException.class, () -> {
|
||||||
|
fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Look for duplicated IPR groups and verify all documents have the same groups assigned
|
||||||
|
// Since there was a ConcurrencyFailureException some threads failed to set extended security so some
|
||||||
|
// documents may not have IPR groups created.
|
||||||
|
verifyCreatedGroups(documents, true);
|
||||||
|
|
||||||
|
AuthenticationUtil.clearCurrentSecurityContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<NodeRef> setupConcurrentTestCase(int concurrentThreads, Set<String> extendedReaders, Set<String> extendedWriters)
|
||||||
|
{
|
||||||
|
final String usera = createTestUser();
|
||||||
|
final String userb = createTestUser();
|
||||||
|
final String owner = createTestUser();
|
||||||
|
|
||||||
|
extendedReaders.add(usera);
|
||||||
|
extendedReaders.add(userb);
|
||||||
|
extendedWriters.add(usera);
|
||||||
|
extendedWriters.add(userb);
|
||||||
|
|
||||||
|
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||||
|
|
||||||
|
// Create a site
|
||||||
|
NodeRef documentLib = createSite(new HashSet<>(), new HashSet<>());
|
||||||
|
|
||||||
|
// Create records in the site document library
|
||||||
|
return createRecords(concurrentThreads, documentLib, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef createSite(Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>() {
|
||||||
|
@Override
|
||||||
|
public NodeRef execute() throws Throwable
|
||||||
|
{
|
||||||
|
final String siteShortName = GUID.generate();
|
||||||
|
siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE);
|
||||||
|
readers.forEach(reader -> siteService.setMembership(siteShortName, reader, SiteModel.SITE_CONSUMER));
|
||||||
|
writers.forEach(writer -> siteService.setMembership(siteShortName, writer, SiteModel.SITE_COLLABORATOR));
|
||||||
|
return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null);
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<NodeRef> createRecords(int numRecords, NodeRef parent, String owner)
|
||||||
|
{
|
||||||
|
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Set<NodeRef>>() {
|
||||||
|
@Override
|
||||||
|
public Set<NodeRef> execute() throws Throwable
|
||||||
|
{
|
||||||
|
int createdRecords = 0;
|
||||||
|
Set<NodeRef> documents = new HashSet<>();
|
||||||
|
while (createdRecords < numRecords)
|
||||||
|
{
|
||||||
|
final NodeRef doc = fileFolderService.create(parent, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
|
||||||
|
ownableService.setOwner(doc, owner);
|
||||||
|
recordService.createRecord(filePlan, doc, rmFolder, true);
|
||||||
|
recordService.file(doc);
|
||||||
|
recordService.complete(doc);
|
||||||
|
documents.add(doc);
|
||||||
|
createdRecords++;
|
||||||
|
}
|
||||||
|
return documents;
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers, boolean useRetry)
|
||||||
|
{
|
||||||
|
if (!useRetry)
|
||||||
|
{
|
||||||
|
setExtendedSecurity(doc, readers, writers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
setExtendedSecurity(doc, readers, writers);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers)
|
||||||
|
{
|
||||||
|
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
|
||||||
|
extendedSecurityService.set(doc, readers, writers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireParallelExecutionOfSetExtendedSecurity(Set<NodeRef> documents, Set<String> extendedReaders, Set<String> extendedWriters, boolean useRetry)
|
||||||
|
{
|
||||||
|
CompletableFuture<?>[] futures = documents.stream()
|
||||||
|
.map(doc -> CompletableFuture.runAsync(() -> setExtendedSecurity(doc, extendedReaders, extendedWriters, useRetry)))
|
||||||
|
.toArray(CompletableFuture[]::new);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CompletableFuture.allOf(futures).join();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Throwable cause = e.getCause();
|
||||||
|
if (cause instanceof ConcurrencyFailureException)
|
||||||
|
{
|
||||||
|
throw (ConcurrencyFailureException) cause;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Error during parallel execution", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyCreatedGroups(Set<NodeRef> documents, boolean onlyDuplicatesValidation)
|
||||||
|
{
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
Set<String> expectedAuthorities = null;
|
||||||
|
Set<Set<String>> errors = new HashSet<>();
|
||||||
|
for (NodeRef doc : documents)
|
||||||
|
{
|
||||||
|
Set<AccessPermission> permissions = permissionService.getAllSetPermissions(doc);
|
||||||
|
Set<String> authorities = getDocumentAuthorities(permissions);
|
||||||
|
Set<String> authoritiesById = getAuthorityIds(authorities);
|
||||||
|
|
||||||
|
verifyIPRGroups(authorities, onlyDuplicatesValidation);
|
||||||
|
|
||||||
|
if (onlyDuplicatesValidation)
|
||||||
|
{
|
||||||
|
// Some documents may not have IPR groups created if there was a ConcurrencyFailureException
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All documents should have the same exact set of groups assigned
|
||||||
|
if (expectedAuthorities == null)
|
||||||
|
{
|
||||||
|
expectedAuthorities = authoritiesById;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expectedAuthorities.equals(authoritiesById))
|
||||||
|
{
|
||||||
|
errors.add(authoritiesById);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue("Unexpected authorities linked to document", errors.isEmpty());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getDocumentAuthorities(Set<AccessPermission> permissions)
|
||||||
|
{
|
||||||
|
Set<String> authorities = new HashSet<>();
|
||||||
|
|
||||||
|
for (AccessPermission accessPermission : permissions)
|
||||||
|
{
|
||||||
|
String authority = accessPermission.getAuthority();
|
||||||
|
String authName = authorityService.getName(AuthorityType.GROUP, authority);
|
||||||
|
authorities.add(authName);
|
||||||
|
|
||||||
|
}
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getAuthorityIds(Set<String> authorities)
|
||||||
|
{
|
||||||
|
Set<String> authorityIds = new HashSet<>();
|
||||||
|
for (String authority : authorities)
|
||||||
|
{
|
||||||
|
String authId = authorityService.getAuthorityNodeRef(authority) != null
|
||||||
|
? authorityService.getAuthorityNodeRef(authority).getId()
|
||||||
|
: null;
|
||||||
|
authorityIds.add(authId);
|
||||||
|
}
|
||||||
|
return authorityIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyIPRGroups(Set<String> authorities, boolean onlyDuplicatesValidation)
|
||||||
|
{
|
||||||
|
boolean hasGroupIPR = false;
|
||||||
|
|
||||||
|
for (String authorityName : authorities)
|
||||||
|
{
|
||||||
|
String shortName = authorityService.getShortName(authorityName);
|
||||||
|
|
||||||
|
if (authorityName.startsWith("GROUP_IPR"))
|
||||||
|
{
|
||||||
|
hasGroupIPR = true;
|
||||||
|
PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP, null, shortName, false,
|
||||||
|
false, new PagingRequest(0, 10));
|
||||||
|
|
||||||
|
assertEquals("No duplicated IPR group expected", 1, results.getPage().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!onlyDuplicatesValidation)
|
||||||
|
{
|
||||||
|
assertTrue("No IPR Groups created", hasGroupIPR);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
# Version label
|
# Version label
|
||||||
version.major=23
|
version.major=23
|
||||||
version.minor=6
|
version.minor=7
|
||||||
version.revision=0
|
version.revision=0
|
||||||
version.label=
|
version.label=
|
||||||
|
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -51,8 +51,8 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-lang</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import org.alfresco.service.cmr.site.SiteInfo;
|
import org.alfresco.service.cmr.site.SiteInfo;
|
||||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
import org.json.simple.JSONObject;
|
import org.json.simple.JSONObject;
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
import org.springframework.extensions.webscripts.Status;
|
import org.springframework.extensions.webscripts.Status;
|
||||||
@@ -92,7 +92,7 @@ public class WikiPageGet extends AbstractWikiWebScript
|
|||||||
{
|
{
|
||||||
links.add(link);
|
links.add(link);
|
||||||
// build the list of available pages
|
// build the list of available pages
|
||||||
WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml(link));
|
WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml4(link));
|
||||||
if (wikiPage != null)
|
if (wikiPage != null)
|
||||||
{
|
{
|
||||||
pageTitles.add(wikiPage.getTitle());
|
pageTitles.add(wikiPage.getTitle());
|
||||||
|
|||||||
@@ -91,6 +91,15 @@ function doclist_getAllNodes(parsedArgs, filterParams, query, totalItemCount)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sanitizeJunkFavouriteKeys(favourites){
|
||||||
|
for (var key in favourites) {
|
||||||
|
if (!key || key.trim() === "") {
|
||||||
|
delete favourites[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return favourites;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point: Create collection of documents and folders in the given space
|
* Main entry point: Create collection of documents and folders in the given space
|
||||||
*
|
*
|
||||||
@@ -123,6 +132,47 @@ function doclist_main()
|
|||||||
|
|
||||||
if (logger.isLoggingEnabled())
|
if (logger.isLoggingEnabled())
|
||||||
logger.log("doclist.lib.js - NodeRef: " + parsedArgs.nodeRef + " Query: " + query);
|
logger.log("doclist.lib.js - NodeRef: " + parsedArgs.nodeRef + " Query: " + query);
|
||||||
|
|
||||||
|
favourites = sanitizeJunkFavouriteKeys(favourites);
|
||||||
|
if(query === null)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
luceneQuery: "",
|
||||||
|
paging: {
|
||||||
|
totalRecords: 0,
|
||||||
|
startIndex: 0
|
||||||
|
},
|
||||||
|
container: parsedArgs.rootNode,
|
||||||
|
parent: null,
|
||||||
|
onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
|
||||||
|
itemCount: {
|
||||||
|
folders: 0,
|
||||||
|
documents: 0
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
customJSON: slingshotDocLib.getJSON()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Object.keys(favourites).length === 0 && query === null)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
luceneQuery: "",
|
||||||
|
paging: {
|
||||||
|
totalRecords: 0,
|
||||||
|
startIndex: 0
|
||||||
|
},
|
||||||
|
container: parsedArgs.rootNode,
|
||||||
|
parent: null,
|
||||||
|
onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
|
||||||
|
itemCount: {
|
||||||
|
folders: 0,
|
||||||
|
documents: 0
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
customJSON: slingshotDocLib.getJSON()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var totalItemCount = filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : -1;
|
var totalItemCount = filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : -1;
|
||||||
// For all sites documentLibrary query we pull in all available results and post filter
|
// For all sites documentLibrary query we pull in all available results and post filter
|
||||||
|
|||||||
@@ -182,11 +182,14 @@ var Filters =
|
|||||||
case "favourites":
|
case "favourites":
|
||||||
for (var favourite in favourites)
|
for (var favourite in favourites)
|
||||||
{
|
{
|
||||||
if (filterQuery)
|
if (favourite && favourite.trim() !== "")
|
||||||
{
|
{
|
||||||
filterQuery += " OR ";
|
if (filterQuery)
|
||||||
|
{
|
||||||
|
filterQuery += " OR ";
|
||||||
|
}
|
||||||
|
filterQuery += "ID:\"" + favourite + "\"";
|
||||||
}
|
}
|
||||||
filterQuery += "ID:\"" + favourite + "\"";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterQuery.length !== 0)
|
if (filterQuery.length !== 0)
|
||||||
@@ -201,7 +204,13 @@ var Filters =
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// empty favourites query
|
// empty favourites query
|
||||||
filterQuery = "+ID:\"\"";
|
logger.warn("No favourites found for user: " + person.properties.userName);
|
||||||
|
return {
|
||||||
|
query: null,
|
||||||
|
limitResults: 0,
|
||||||
|
sort: [],
|
||||||
|
language: "lucene"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
filterParams.query = filterQuery;
|
filterParams.query = filterQuery;
|
||||||
@@ -224,15 +233,15 @@ var Filters =
|
|||||||
filterParams.query = "+ID:\"" + parsedArgs.nodeRef + "\"";
|
filterParams.query = "+ID:\"" + parsedArgs.nodeRef + "\"";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "tag":
|
case "tag":
|
||||||
// Remove any trailing "/" character
|
// Remove any trailing "/" character
|
||||||
if (filterData.charAt(filterData.length - 1) == "/")
|
if (filterData.charAt(filterData.length - 1) == "/")
|
||||||
{
|
{
|
||||||
filterData = filterData.slice(0, -1);
|
filterData = filterData.slice(0, -1);
|
||||||
}
|
}
|
||||||
filterQuery = this.constructPathQuery(parsedArgs);
|
filterQuery = this.constructPathQuery(parsedArgs);
|
||||||
filterParams.query = filterQuery + " +PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(filterData) + "/member\"";
|
filterParams.query = filterQuery + " +TAG:\"" + search.ISO9075Encode(filterData) + "\"";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "category":
|
case "category":
|
||||||
// Remove any trailing "/" character
|
// Remove any trailing "/" character
|
||||||
@@ -240,8 +249,15 @@ var Filters =
|
|||||||
{
|
{
|
||||||
filterData = filterData.slice(0, -1);
|
filterData = filterData.slice(0, -1);
|
||||||
}
|
}
|
||||||
filterQuery = this.constructPathQuery(parsedArgs);
|
|
||||||
filterParams.query = filterQuery + " +PATH:\"/cm:categoryRoot/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\"";
|
var categoryNodeRef = this.getCategoryNodeRef(filterData);
|
||||||
|
|
||||||
|
if (categoryNodeRef && search.findNode(categoryNodeRef) != null) {
|
||||||
|
filterParams.query = filterQuery + ' +@cm\\:categories:"' + categoryNodeRef + '"';
|
||||||
|
} else {
|
||||||
|
logger.warn("category filter: skipping invalid category node : " + categoryNodeRef);
|
||||||
|
}
|
||||||
|
filterParams.language = "fts-alfresco";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "aspect":
|
case "aspect":
|
||||||
@@ -262,11 +278,24 @@ var Filters =
|
|||||||
{
|
{
|
||||||
filterParams.query += " " + (Filters.TYPE_MAP[parsedArgs.type] || "");
|
filterParams.query += " " + (Filters.TYPE_MAP[parsedArgs.type] || "");
|
||||||
}
|
}
|
||||||
|
logger.warn("Final Query : " + filterParams.query);
|
||||||
return filterParams;
|
return filterParams;
|
||||||
},
|
},
|
||||||
|
|
||||||
constructPathQuery: function constructPathQuery(parsedArgs)
|
getCategoryNodeRef: function(categoryName) {
|
||||||
|
var results = search.luceneSearch(
|
||||||
|
'PATH:"/cm:categoryRoot/cm:generalclassifiable//*" AND @cm\\:name:"' + categoryName + '"'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results && results.length > 0) {
|
||||||
|
return results[0].nodeRef.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.warn("Category not found: " + categoryName);
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
constructPathQuery: function(parsedArgs)
|
||||||
{
|
{
|
||||||
var pathQuery = "";
|
var pathQuery = "";
|
||||||
if (parsedArgs.libraryRoot != companyhome || parsedArgs.nodeRef != "alfresco://company/home")
|
if (parsedArgs.libraryRoot != companyhome || parsedArgs.nodeRef != "alfresco://company/home")
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
|||||||
import org.alfresco.service.cmr.wiki.WikiService;
|
import org.alfresco.service.cmr.wiki.WikiService;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.alfresco.util.PropertyMap;
|
import org.alfresco.util.PropertyMap;
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
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.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@@ -996,7 +996,7 @@ public class WikiRestApiTest extends BaseWebScriptTest
|
|||||||
String link = m.group(1);
|
String link = m.group(1);
|
||||||
link += "?title=<script>alert('xss');</script>";
|
link += "?title=<script>alert('xss');</script>";
|
||||||
WikiPageInfo wikiPage2 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, link);
|
WikiPageInfo wikiPage2 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, link);
|
||||||
WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml(link));
|
WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml4(link));
|
||||||
assertEquals(wikiPage2, wikiPage1);
|
assertEquals(wikiPage2, wikiPage1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1006,4 +1006,4 @@ public class WikiRestApiTest extends BaseWebScriptTest
|
|||||||
this.wikiService.deleteWikiPage(wikiPageNew);
|
this.wikiService.deleteWikiPage(wikiPageNew);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ commons-email http://jakarta.apache.org/commons/
|
|||||||
commons-fileupload http://jakarta.apache.org/commons/
|
commons-fileupload http://jakarta.apache.org/commons/
|
||||||
commons-httpclient http://jakarta.apache.org/commons/
|
commons-httpclient http://jakarta.apache.org/commons/
|
||||||
commons-io http://jakarta.apache.org/commons/
|
commons-io http://jakarta.apache.org/commons/
|
||||||
commons-jxpath http://jakarta.apache.org/commons/
|
commons-jxpath http://jakarta.apache.org/commons/
|
||||||
commons-lang http://jakarta.apache.org/commons/
|
|
||||||
commons-lang3 http://jakarta.apache.org/commons/
|
commons-lang3 http://jakarta.apache.org/commons/
|
||||||
commons-logging http://jakarta.apache.org/commons/
|
commons-logging http://jakarta.apache.org/commons/
|
||||||
commons-net http://jakarta.apache.org/commons/
|
commons-net http://jakarta.apache.org/commons/
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
SOLR6_TAG=2.0.13
|
SOLR6_TAG=2.0.17
|
||||||
POSTGRES_TAG=15.4
|
POSTGRES_TAG=15.4
|
||||||
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.alfresco.utility.testrail.annotation.TestRail;
|
|||||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
|
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
|
||||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
|
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
|
||||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
|
import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException;
|
||||||
import org.apache.commons.lang.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<rest.api.explorer.branch>master</rest.api.explorer.branch>
|
<rest.api.explorer.branch>master</rest.api.explorer.branch>
|
||||||
<httpclient-osgi-version>4.5.6</httpclient-osgi-version>
|
<httpclient-osgi-version>4.5.6</httpclient-osgi-version>
|
||||||
<commons-lang3.version>3.17.0</commons-lang3.version>
|
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||||
<scribejava-apis.version>8.3.3</scribejava-apis.version>
|
<scribejava-apis.version>8.3.3</scribejava-apis.version>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
46
pom.xml
46
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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Alfresco Community Repo Parent</name>
|
<name>Alfresco Community Repo Parent</name>
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<acs.version.major>23</acs.version.major>
|
<acs.version.major>23</acs.version.major>
|
||||||
<acs.version.minor>6</acs.version.minor>
|
<acs.version.minor>7</acs.version.minor>
|
||||||
<acs.version.revision>0</acs.version.revision>
|
<acs.version.revision>0</acs.version.revision>
|
||||||
<acs.version.label />
|
<acs.version.label />
|
||||||
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
||||||
@@ -51,17 +51,17 @@
|
|||||||
<dependency.alfresco-server-root.version>7.0.1</dependency.alfresco-server-root.version>
|
<dependency.alfresco-server-root.version>7.0.1</dependency.alfresco-server-root.version>
|
||||||
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
||||||
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
||||||
<dependency.alfresco-transform-core.version>5.1.5</dependency.alfresco-transform-core.version>
|
<dependency.alfresco-transform-core.version>5.2.2</dependency.alfresco-transform-core.version>
|
||||||
<dependency.alfresco-transform-service.version>4.1.5</dependency.alfresco-transform-service.version>
|
<dependency.alfresco-transform-service.version>4.2.2</dependency.alfresco-transform-service.version>
|
||||||
<dependency.alfresco-greenmail.version>7.0</dependency.alfresco-greenmail.version>
|
<dependency.alfresco-greenmail.version>7.0</dependency.alfresco-greenmail.version>
|
||||||
<dependency.acs-event-model.version>0.0.33</dependency.acs-event-model.version>
|
<dependency.acs-event-model.version>0.0.33</dependency.acs-event-model.version>
|
||||||
|
|
||||||
<dependency.aspectj.version>1.9.22.1</dependency.aspectj.version>
|
<dependency.aspectj.version>1.9.22.1</dependency.aspectj.version>
|
||||||
<dependency.spring.version>6.2.8</dependency.spring.version>
|
<dependency.spring.version>6.2.11</dependency.spring.version>
|
||||||
<dependency.spring-security.version>6.3.9</dependency.spring-security.version>
|
<dependency.spring-security.version>6.4.11</dependency.spring-security.version>
|
||||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||||
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
<dependency.jackson.version>2.17.2</dependency.jackson.version>
|
||||||
<dependency.cxf.version>4.1.0</dependency.cxf.version>
|
<dependency.cxf.version>4.1.2</dependency.cxf.version>
|
||||||
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
|
<dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version>
|
||||||
<dependency.webscripts.version>10.2</dependency.webscripts.version>
|
<dependency.webscripts.version>10.2</dependency.webscripts.version>
|
||||||
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
|
<dependency.bouncycastle.version>1.78.1</dependency.bouncycastle.version>
|
||||||
@@ -81,12 +81,12 @@
|
|||||||
<dependency.slf4j.version>2.0.16</dependency.slf4j.version>
|
<dependency.slf4j.version>2.0.16</dependency.slf4j.version>
|
||||||
<dependency.log4j.version>2.23.1</dependency.log4j.version>
|
<dependency.log4j.version>2.23.1</dependency.log4j.version>
|
||||||
<dependency.groovy.version>3.0.22</dependency.groovy.version>
|
<dependency.groovy.version>3.0.22</dependency.groovy.version>
|
||||||
<dependency.tika.version>2.9.2</dependency.tika.version>
|
<dependency.tika.version>3.2.3</dependency.tika.version>
|
||||||
<dependency.truezip.version>7.7.10</dependency.truezip.version>
|
<dependency.truezip.version>7.7.10</dependency.truezip.version>
|
||||||
<dependency.poi.version>5.4.1</dependency.poi.version>
|
<dependency.poi.version>5.4.1</dependency.poi.version>
|
||||||
<dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
|
<dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
|
||||||
<dependency.camel.version>4.10.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
|
<dependency.camel.version>4.15.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
|
||||||
<dependency.netty.version>4.1.118.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common -->
|
<dependency.netty.version>4.1.127.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common -->
|
||||||
<dependency.activemq.version>5.18.3</dependency.activemq.version>
|
<dependency.activemq.version>5.18.3</dependency.activemq.version>
|
||||||
<dependency.apache-compress.version>1.27.1</dependency.apache-compress.version>
|
<dependency.apache-compress.version>1.27.1</dependency.apache-compress.version>
|
||||||
<dependency.awaitility.version>4.2.2</dependency.awaitility.version>
|
<dependency.awaitility.version>4.2.2</dependency.awaitility.version>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
<dependency.jakarta-annotation-api.version>3.0.0</dependency.jakarta-annotation-api.version>
|
<dependency.jakarta-annotation-api.version>3.0.0</dependency.jakarta-annotation-api.version>
|
||||||
<dependency.jakarta-transaction-api.version>2.0.1</dependency.jakarta-transaction-api.version>
|
<dependency.jakarta-transaction-api.version>2.0.1</dependency.jakarta-transaction-api.version>
|
||||||
<dependency.jakarta-jws-api.version>3.0.0</dependency.jakarta-jws-api.version>
|
<dependency.jakarta-jws-api.version>3.0.0</dependency.jakarta-jws-api.version>
|
||||||
<dependency.jakarta-ee-mail.version>2.0.1</dependency.jakarta-ee-mail.version>
|
<dependency.jakarta-ee-mail.version>2.0.2</dependency.jakarta-ee-mail.version>
|
||||||
<dependency.jakarta-ee-activation.version>2.0.1</dependency.jakarta-ee-activation.version>
|
<dependency.jakarta-ee-activation.version>2.0.1</dependency.jakarta-ee-activation.version>
|
||||||
<dependency.jakarta-ee-jms.version>3.1.0</dependency.jakarta-ee-jms.version>
|
<dependency.jakarta-ee-jms.version>3.1.0</dependency.jakarta-ee-jms.version>
|
||||||
<dependency.java-ee-activation.version>1.2.0</dependency.java-ee-activation.version>
|
<dependency.java-ee-activation.version>1.2.0</dependency.java-ee-activation.version>
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
|
<dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version>
|
||||||
<dependency.json-smart.version>2.5.2</dependency.json-smart.version>
|
<dependency.json-smart.version>2.5.2</dependency.json-smart.version>
|
||||||
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
|
<alfresco.googledrive.version>4.1.0</alfresco.googledrive.version>
|
||||||
<alfresco.aos-module.version>3.3.0</alfresco.aos-module.version>
|
<alfresco.aos-module.version>3.4.0</alfresco.aos-module.version>
|
||||||
<alfresco.api-explorer.version>23.4.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
<alfresco.api-explorer.version>23.4.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||||
|
|
||||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||||
@@ -154,7 +154,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>23.6.0.9</tag>
|
<tag>23.7.0.6</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@@ -170,6 +170,12 @@
|
|||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- v1.10 has 0BSD license it must be consulted with Legal -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.tukaani</groupId>
|
||||||
|
<artifactId>xz</artifactId>
|
||||||
|
<version>1.9</version>
|
||||||
|
</dependency>
|
||||||
<!-- Jakarta... -->
|
<!-- Jakarta... -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.xml.bind</groupId>
|
<groupId>jakarta.xml.bind</groupId>
|
||||||
@@ -417,9 +423,9 @@
|
|||||||
<version>1.17.1</version>
|
<version>1.17.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-lang</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>2.6</version>
|
<version>3.18.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
@@ -1132,16 +1138,10 @@
|
|||||||
<exclude>jakarta.xml.soap:jakarta.xml.soap-api:(, 2.0.1)</exclude>
|
<exclude>jakarta.xml.soap:jakarta.xml.soap-api:(, 2.0.1)</exclude>
|
||||||
<exclude>jakarta.jws:jakarta.jws-api:(, 3.0.0)</exclude>
|
<exclude>jakarta.jws:jakarta.jws-api:(, 3.0.0)</exclude>
|
||||||
<!-- Enforce ban bouncycastle dependencies other than specified under <includes> section-->
|
<!-- Enforce ban bouncycastle dependencies other than specified under <includes> section-->
|
||||||
<exclude>org.bouncycastle</exclude>
|
<exclude>org.bouncycastle:(,1.81)</exclude>
|
||||||
<!-- Enforce one version of Jaxb-->
|
<!-- Enforce one version of Jaxb-->
|
||||||
<exclude>com.sun.xml.bind</exclude>
|
<exclude>com.sun.xml.bind</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
<includes>
|
|
||||||
<include>org.bouncycastle:bcprov-jdk18on:[1.78.1,)</include>
|
|
||||||
<include>org.bouncycastle:bcmail-jdk18on:[1.78.1,)</include>
|
|
||||||
<include>org.bouncycastle:bcpkix-jdk18on:[1.78.1,)</include>
|
|
||||||
<include>org.bouncycastle:bcutil-jdk18on:[1.78.1,)</include>
|
|
||||||
</includes>
|
|
||||||
</bannedDependencies>
|
</bannedDependencies>
|
||||||
</rules>
|
</rules>
|
||||||
<fail>true</fail>
|
<fail>true</fail>
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Remote API
|
* Alfresco Remote API
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 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
|
||||||
@@ -31,6 +31,14 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.owasp.html.HtmlPolicyBuilder;
|
||||||
|
import org.owasp.html.PolicyFactory;
|
||||||
|
import org.springframework.extensions.webscripts.Cache;
|
||||||
|
import org.springframework.extensions.webscripts.Status;
|
||||||
|
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.ForumModel;
|
import org.alfresco.model.ForumModel;
|
||||||
import org.alfresco.repo.content.MimetypeMap;
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
@@ -44,10 +52,6 @@ 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.alfresco.service.namespace.RegexQNamePattern;
|
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
import org.springframework.extensions.webscripts.Cache;
|
|
||||||
import org.springframework.extensions.webscripts.Status;
|
|
||||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is the controller for the comments.post web script.
|
* This class is the controller for the comments.post web script.
|
||||||
@@ -58,7 +62,7 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
|
|||||||
public class CommentsPost extends AbstractCommentsWebScript
|
public class CommentsPost extends AbstractCommentsWebScript
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Overrides AbstractCommentsWebScript to add comment
|
* Overrides AbstractCommentsWebScript to add comment
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Map<String, Object> executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache)
|
protected Map<String, Object> executeImpl(NodeRef nodeRef, WebScriptRequest req, Status status, Cache cache)
|
||||||
@@ -66,6 +70,29 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
// get json object from request
|
// get json object from request
|
||||||
JSONObject json = parseJSON(req);
|
JSONObject json = parseJSON(req);
|
||||||
|
|
||||||
|
// Validating and Sanitizing comment content to prevent XSS
|
||||||
|
String commentContent = getOrNull(json, "content");
|
||||||
|
if (StringUtils.isBlank(commentContent))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Comment content must not be empty");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Allowed HTML elements and attributes in comment content e.g. Text formatting ,Lists and Structure & Styling
|
||||||
|
String[] allowedElements = {"b", "i", "u", "strong", "em", "ul", "ol", "li", "p", "br", "span", "div"};
|
||||||
|
|
||||||
|
PolicyFactory policy = new HtmlPolicyBuilder()
|
||||||
|
.allowElements(allowedElements)
|
||||||
|
.allowAttributes("style")
|
||||||
|
.onElements("span", "div", "p", "ul")
|
||||||
|
.allowStyling()
|
||||||
|
.allowStandardUrlProtocols()
|
||||||
|
.toFactory();
|
||||||
|
|
||||||
|
String safeContent = policy.sanitize(commentContent);
|
||||||
|
json.replace("content", safeContent);
|
||||||
|
}
|
||||||
|
|
||||||
/* MNT-10231, MNT-9771 fix */
|
/* MNT-10231, MNT-9771 fix */
|
||||||
this.behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
this.behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
|
||||||
@@ -99,32 +126,32 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
{
|
{
|
||||||
// fetch the parent to add the node to
|
// fetch the parent to add the node to
|
||||||
NodeRef commentsFolder = getOrCreateCommentsFolder(nodeRef);
|
NodeRef commentsFolder = getOrCreateCommentsFolder(nodeRef);
|
||||||
|
|
||||||
// get a unique name
|
// get a unique name
|
||||||
String name = getUniqueChildName("comment");
|
String name = getUniqueChildName("comment");
|
||||||
|
|
||||||
// create the comment
|
// create the comment
|
||||||
NodeRef commentNodeRef = nodeService.createNode(commentsFolder,
|
NodeRef commentNodeRef = nodeService.createNode(commentsFolder,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)),
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName(name)),
|
||||||
ForumModel.TYPE_POST).getChildRef();
|
ForumModel.TYPE_POST).getChildRef();
|
||||||
|
|
||||||
// fetch the title required to create a comment
|
// fetch the title required to create a comment
|
||||||
String title = getOrNull(json, JSON_KEY_TITLE);
|
String title = getOrNull(json, JSON_KEY_TITLE);
|
||||||
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
|
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
|
||||||
props.put(ContentModel.PROP_TITLE, title != null ? title : "");
|
props.put(ContentModel.PROP_TITLE, title != null ? title : "");
|
||||||
nodeService.addProperties(commentNodeRef, props);
|
nodeService.addProperties(commentNodeRef, props);
|
||||||
|
|
||||||
ContentWriter writer = contentService.getWriter(commentNodeRef, ContentModel.PROP_CONTENT, true);
|
ContentWriter writer = contentService.getWriter(commentNodeRef, ContentModel.PROP_CONTENT, true);
|
||||||
// fetch the content of a comment
|
// fetch the content of a comment
|
||||||
String contentString = getOrNull(json, JSON_KEY_CONTENT);
|
String contentString = getOrNull(json, JSON_KEY_CONTENT);
|
||||||
|
|
||||||
writer.setMimetype(MimetypeMap.MIMETYPE_HTML);
|
writer.setMimetype(MimetypeMap.MIMETYPE_HTML);
|
||||||
writer.putContent(contentString);
|
writer.putContent(contentString);
|
||||||
|
|
||||||
return commentNodeRef;
|
return commentNodeRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generates an comment item value
|
* generates an comment item value
|
||||||
*
|
*
|
||||||
@@ -134,34 +161,34 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
private Map<String, Object> generateItemValue(NodeRef commentNodeRef)
|
private Map<String, Object> generateItemValue(NodeRef commentNodeRef)
|
||||||
{
|
{
|
||||||
Map<String, Object> result = new HashMap<String, Object>(4, 1.0f);
|
Map<String, Object> result = new HashMap<String, Object>(4, 1.0f);
|
||||||
|
|
||||||
String creator = (String)this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATOR);
|
String creator = (String) this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATOR);
|
||||||
|
|
||||||
Serializable created = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATED);
|
Serializable created = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_CREATED);
|
||||||
Serializable modified = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_MODIFIED);
|
Serializable modified = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_MODIFIED);
|
||||||
|
|
||||||
boolean isUpdated = false;
|
boolean isUpdated = false;
|
||||||
if (created instanceof Date && modified instanceof Date)
|
if (created instanceof Date && modified instanceof Date)
|
||||||
{
|
{
|
||||||
isUpdated = ((Date)modified).getTime() - ((Date)created).getTime() > 5000;
|
isUpdated = ((Date) modified).getTime() - ((Date) created).getTime() > 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO refactor v0 Comments API to use CommentService (see ACE-5437)
|
// TODO refactor v0 Comments API to use CommentService (see ACE-5437)
|
||||||
Serializable owner = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_OWNER);
|
Serializable owner = this.nodeService.getProperty(commentNodeRef, ContentModel.PROP_OWNER);
|
||||||
String currentUser = this.serviceRegistry.getAuthenticationService().getCurrentUserName();
|
String currentUser = this.serviceRegistry.getAuthenticationService().getCurrentUserName();
|
||||||
|
|
||||||
boolean isSiteManager = this.permissionService.hasPermission(commentNodeRef, SiteModel.SITE_MANAGER) == (AccessStatus.ALLOWED);
|
boolean isSiteManager = this.permissionService.hasPermission(commentNodeRef, SiteModel.SITE_MANAGER) == (AccessStatus.ALLOWED);
|
||||||
boolean isCoordinator = this.permissionService.hasPermission(commentNodeRef, PermissionService.COORDINATOR) == (AccessStatus.ALLOWED);
|
boolean isCoordinator = this.permissionService.hasPermission(commentNodeRef, PermissionService.COORDINATOR) == (AccessStatus.ALLOWED);
|
||||||
boolean canEditComment = isSiteManager || isCoordinator || currentUser.equals(creator) || currentUser.equals(owner);
|
boolean canEditComment = isSiteManager || isCoordinator || currentUser.equals(creator) || currentUser.equals(owner);
|
||||||
|
|
||||||
result.put("node", commentNodeRef);
|
result.put("node", commentNodeRef);
|
||||||
result.put("author", this.personService.getPerson(creator));
|
result.put("author", this.personService.getPerson(creator));
|
||||||
result.put("isUpdated", isUpdated);
|
result.put("isUpdated", isUpdated);
|
||||||
result.put("canEditComment", canEditComment);
|
result.put("canEditComment", canEditComment);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generates the response model for adding a comment
|
* generates the response model for adding a comment
|
||||||
*
|
*
|
||||||
@@ -194,7 +221,7 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
}
|
}
|
||||||
return commentsFolder;
|
return commentsFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the nodeRef of the existing one
|
* returns the nodeRef of the existing one
|
||||||
*
|
*
|
||||||
@@ -207,7 +234,7 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
{
|
{
|
||||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL);
|
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL);
|
||||||
ChildAssociationRef firstAssoc = assocs.get(0);
|
ChildAssociationRef firstAssoc = assocs.get(0);
|
||||||
|
|
||||||
return nodeService.getChildByName(firstAssoc.getChildRef(), ContentModel.ASSOC_CONTAINS, COMMENTS_TOPIC_NAME);
|
return nodeService.getChildByName(firstAssoc.getChildRef(), ContentModel.ASSOC_CONTAINS, COMMENTS_TOPIC_NAME);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -220,7 +247,7 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
{
|
{
|
||||||
return prefix + "-" + System.currentTimeMillis();
|
return prefix + "-" + System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates the comments folder if it does not exists
|
* creates the comments folder if it does not exists
|
||||||
*
|
*
|
||||||
@@ -229,35 +256,34 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
*/
|
*/
|
||||||
private NodeRef createCommentsFolder(final NodeRef nodeRef)
|
private NodeRef createCommentsFolder(final NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
NodeRef commentsFolder = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<NodeRef>()
|
NodeRef commentsFolder = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<NodeRef>() {
|
||||||
{
|
|
||||||
public NodeRef doWork() throws Exception
|
public NodeRef doWork() throws Exception
|
||||||
{
|
{
|
||||||
NodeRef commentsFolder = null;
|
NodeRef commentsFolder = null;
|
||||||
AuthenticationUtil.pushAuthentication();
|
AuthenticationUtil.pushAuthentication();
|
||||||
|
|
||||||
// ALF-5240: turn off auditing round the discussion node creation to prevent
|
// ALF-5240: turn off auditing round the discussion node creation to prevent
|
||||||
// the source document from being modified by the first user leaving a comment
|
// the source document from being modified by the first user leaving a comment
|
||||||
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
behaviourFilter.disableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// MNT-12082: set System user for creating forumFolder and commentsFolder nodes
|
// MNT-12082: set System user for creating forumFolder and commentsFolder nodes
|
||||||
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
nodeService.addAspect(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussable"), null);
|
nodeService.addAspect(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussable"), null);
|
||||||
nodeService.addAspect(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "commentsRollup"), null);
|
nodeService.addAspect(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "commentsRollup"), null);
|
||||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussion"), RegexQNamePattern.MATCH_ALL);
|
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "discussion"), RegexQNamePattern.MATCH_ALL);
|
||||||
if (assocs.size() != 0)
|
if (assocs.size() != 0)
|
||||||
{
|
{
|
||||||
NodeRef forumFolder = assocs.get(0).getChildRef();
|
NodeRef forumFolder = assocs.get(0).getChildRef();
|
||||||
|
|
||||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
|
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1, 1.0f);
|
||||||
props.put(ContentModel.PROP_NAME, COMMENTS_TOPIC_NAME);
|
props.put(ContentModel.PROP_NAME, COMMENTS_TOPIC_NAME);
|
||||||
commentsFolder = nodeService.createNode(
|
commentsFolder = nodeService.createNode(
|
||||||
forumFolder,
|
forumFolder,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, COMMENTS_TOPIC_NAME),
|
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, COMMENTS_TOPIC_NAME),
|
||||||
QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "topic"),
|
QName.createQName(NamespaceService.FORUMS_MODEL_1_0_URI, "topic"),
|
||||||
props).getChildRef();
|
props).getChildRef();
|
||||||
}
|
}
|
||||||
@@ -267,12 +293,12 @@ public class CommentsPost extends AbstractCommentsWebScript
|
|||||||
AuthenticationUtil.popAuthentication();
|
AuthenticationUtil.popAuthentication();
|
||||||
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
behaviourFilter.enableBehaviour(nodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return commentsFolder;
|
return commentsFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
return commentsFolder;
|
return commentsFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>23.6.0.9</version>
|
<version>23.7.0.6</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -94,7 +94,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.18.0</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
@@ -742,10 +741,6 @@
|
|||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-lang</groupId>
|
|
||||||
<artifactId>commons-lang</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 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
|
||||||
@@ -23,105 +23,102 @@
|
|||||||
* 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.domain.node;
|
package org.alfresco.repo.domain.node;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class holding properties associated with the <b>sys:referenceable</b> aspect.
|
* Class holding properties associated with the <b>sys:referenceable</b> aspect. This aspect is common enough to warrant direct inclusion on the <b>Node</b> entity.
|
||||||
* This aspect is common enough to warrant direct inclusion on the <b>Node</b> entity.
|
*
|
||||||
*
|
* @author Derek Hulley
|
||||||
* @author Derek Hulley
|
* @since 3.4
|
||||||
* @since 3.4
|
*/
|
||||||
*/
|
public class ReferenceablePropertiesEntity
|
||||||
public class ReferenceablePropertiesEntity
|
{
|
||||||
{
|
private static final Set<QName> REFERENCEABLE_PROP_QNAMES;
|
||||||
private static final Set<QName> REFERENCEABLE_PROP_QNAMES;
|
static
|
||||||
static
|
{
|
||||||
{
|
REFERENCEABLE_PROP_QNAMES = new HashSet<QName>(8);
|
||||||
REFERENCEABLE_PROP_QNAMES = new HashSet<QName>(8);
|
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_STORE_PROTOCOL);
|
||||||
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_STORE_PROTOCOL);
|
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_STORE_IDENTIFIER);
|
||||||
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_STORE_IDENTIFIER);
|
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_NODE_UUID);
|
||||||
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_NODE_UUID);
|
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_NODE_DBID);
|
||||||
REFERENCEABLE_PROP_QNAMES.add(ContentModel.PROP_NODE_DBID);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @return Returns <tt>true</tt> if the property belongs to the <b>sys:referenceable</b> aspect
|
||||||
* @return Returns <tt>true</tt> if the property belongs to the <b>sys:referenceable</b> aspect
|
*/
|
||||||
*/
|
public static boolean isReferenceableProperty(QName qname)
|
||||||
public static boolean isReferenceableProperty(QName qname)
|
{
|
||||||
{
|
return REFERENCEABLE_PROP_QNAMES.contains(qname);
|
||||||
return REFERENCEABLE_PROP_QNAMES.contains(qname);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Remove all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties
|
||||||
* Remove all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties
|
*/
|
||||||
*/
|
public static void removeReferenceableProperties(Node node, Map<QName, Serializable> properties)
|
||||||
public static void removeReferenceableProperties(Node node, Map<QName, Serializable> properties)
|
{
|
||||||
{
|
properties.keySet().removeAll(REFERENCEABLE_PROP_QNAMES);
|
||||||
properties.keySet().removeAll(REFERENCEABLE_PROP_QNAMES);
|
String name = DefaultTypeConverter.INSTANCE.convert(String.class, properties.get(ContentModel.PROP_NAME));
|
||||||
String name = DefaultTypeConverter.INSTANCE.convert(String.class, properties.get(ContentModel.PROP_NAME));
|
if (name != null && name.equals(node.getUuid()))
|
||||||
if (name != null && name.equals(node.getUuid()))
|
{
|
||||||
{
|
// The cm:name matches the UUID, so drop it
|
||||||
// The cm:name matches the UUID, so drop it
|
properties.remove(ContentModel.PROP_NAME);
|
||||||
properties.remove(ContentModel.PROP_NAME);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Remove all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties
|
||||||
* Remove all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties
|
*/
|
||||||
*/
|
public static void removeReferenceableProperties(Set<QName> propertyQNames)
|
||||||
public static void removeReferenceableProperties(Set<QName> propertyQNames)
|
{
|
||||||
{
|
propertyQNames.removeAll(REFERENCEABLE_PROP_QNAMES);
|
||||||
propertyQNames.removeAll(REFERENCEABLE_PROP_QNAMES);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties.
|
||||||
* Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties.
|
*/
|
||||||
*/
|
public static void addReferenceableProperties(Long nodeId, NodeRef nodeRef, Map<QName, Serializable> properties)
|
||||||
public static void addReferenceableProperties(Node node, Map<QName, Serializable> properties)
|
{
|
||||||
{
|
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
|
||||||
Long nodeId = node.getId();
|
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
|
||||||
NodeRef nodeRef = node.getNodeRef();
|
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());
|
||||||
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
|
properties.put(ContentModel.PROP_NODE_DBID, nodeId);
|
||||||
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
|
// add the ID as the name, if required
|
||||||
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());
|
String name = DefaultTypeConverter.INSTANCE.convert(String.class, properties.get(ContentModel.PROP_NAME));
|
||||||
properties.put(ContentModel.PROP_NODE_DBID, nodeId);
|
if (name == null)
|
||||||
// add the ID as the name, if required
|
{
|
||||||
String name = DefaultTypeConverter.INSTANCE.convert(String.class, properties.get(ContentModel.PROP_NAME));
|
properties.put(ContentModel.PROP_NAME, nodeRef.getId());
|
||||||
if (name == null)
|
}
|
||||||
{
|
}
|
||||||
properties.put(ContentModel.PROP_NAME, nodeRef.getId());
|
|
||||||
}
|
public static Serializable getReferenceableProperty(Node node, QName qname)
|
||||||
}
|
{
|
||||||
|
NodeRef nodeRef = node.getNodeRef();
|
||||||
public static Serializable getReferenceableProperty(Node node, QName qname)
|
if (qname.equals(ContentModel.PROP_STORE_PROTOCOL))
|
||||||
{
|
{
|
||||||
NodeRef nodeRef = node.getNodeRef();
|
return nodeRef.getStoreRef().getProtocol();
|
||||||
if (qname.equals(ContentModel.PROP_STORE_PROTOCOL))
|
}
|
||||||
{
|
else if (qname.equals(ContentModel.PROP_STORE_IDENTIFIER))
|
||||||
return nodeRef.getStoreRef().getProtocol();
|
{
|
||||||
}
|
return nodeRef.getStoreRef().getIdentifier();
|
||||||
else if (qname.equals(ContentModel.PROP_STORE_IDENTIFIER))
|
}
|
||||||
{
|
else if (qname.equals(ContentModel.PROP_NODE_UUID))
|
||||||
return nodeRef.getStoreRef().getIdentifier();
|
{
|
||||||
}
|
return nodeRef.getId();
|
||||||
else if (qname.equals(ContentModel.PROP_NODE_UUID))
|
}
|
||||||
{
|
else if (qname.equals(ContentModel.PROP_NODE_DBID))
|
||||||
return nodeRef.getId();
|
{
|
||||||
}
|
return node.getId();
|
||||||
else if (qname.equals(ContentModel.PROP_NODE_DBID))
|
}
|
||||||
{
|
throw new IllegalArgumentException("Not sys:referenceable property: " + qname);
|
||||||
return node.getId();
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Not sys:referenceable property: " + qname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
private static final String SELECT_NODE_MAX_ID = "alfresco.node.select_NodeMaxId";
|
private static final String SELECT_NODE_MAX_ID = "alfresco.node.select_NodeMaxId";
|
||||||
private static final String SELECT_NODE_INTERVAL_BY_TYPE = "alfresco.node.select_MinMaxNodeIdForNodeType";
|
private static final String SELECT_NODE_INTERVAL_BY_TYPE = "alfresco.node.select_MinMaxNodeIdForNodeType";
|
||||||
private static final String SELECT_NODES_WITH_ASPECT_IDS = "alfresco.node.select_NodesWithAspectIds";
|
private static final String SELECT_NODES_WITH_ASPECT_IDS = "alfresco.node.select_NodesWithAspectIds";
|
||||||
private static final String SELECT_NODES_WITH_ASPECT_IDS_LIMITED = "alfresco.node.select_NodesWithAspectIds_Limited";
|
private static final String SELECT_NODES_WITH_ASPECT_IDS_LIMITED = "alfresco.node.select.select_NodesWithAspectIds_Limited";
|
||||||
private static final String INSERT_NODE_ASSOC = "alfresco.node.insert.insert_NodeAssoc";
|
private static final String INSERT_NODE_ASSOC = "alfresco.node.insert.insert_NodeAssoc";
|
||||||
private static final String UPDATE_NODE_ASSOC = "alfresco.node.update_NodeAssoc";
|
private static final String UPDATE_NODE_ASSOC = "alfresco.node.update_NodeAssoc";
|
||||||
private static final String DELETE_NODE_ASSOC = "alfresco.node.delete_NodeAssoc";
|
private static final String DELETE_NODE_ASSOC = "alfresco.node.delete_NodeAssoc";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 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
|
||||||
@@ -39,8 +39,10 @@ import org.alfresco.service.namespace.QName;
|
|||||||
/**
|
/**
|
||||||
* Encapsulates events occurred in a single transaction.
|
* Encapsulates events occurred in a single transaction.
|
||||||
*
|
*
|
||||||
* @param <REF> entity (e.g. node, child association, peer association) reference type
|
* @param <REF>
|
||||||
* @param <RES> entity resource type
|
* entity (e.g. node, child association, peer association) reference type
|
||||||
|
* @param <RES>
|
||||||
|
* entity resource type
|
||||||
*/
|
*/
|
||||||
public abstract class EventConsolidator<REF extends EntityRef, RES extends Resource>
|
public abstract class EventConsolidator<REF extends EntityRef, RES extends Resource>
|
||||||
{
|
{
|
||||||
@@ -90,23 +92,31 @@ public abstract class EventConsolidator<REF extends EntityRef, RES extends Resou
|
|||||||
/**
|
/**
|
||||||
* Builds and returns the {@link RepoEvent} instance.
|
* Builds and returns the {@link RepoEvent} instance.
|
||||||
*
|
*
|
||||||
* @param eventInfo the object holding the event information
|
* @param eventInfo
|
||||||
|
* the object holding the event information
|
||||||
* @return the {@link RepoEvent} instance
|
* @return the {@link RepoEvent} instance
|
||||||
*/
|
*/
|
||||||
public RepoEvent<DataAttributes<RES>> getRepoEvent(EventInfo eventInfo)
|
public RepoEvent<DataAttributes<RES>> getRepoEvent(EventInfo eventInfo)
|
||||||
|
{
|
||||||
|
final RepoEvent.Builder<DataAttributes<RES>> builder = RepoEvent.builder();
|
||||||
|
|
||||||
|
configureRepoEventBuilder(builder, eventInfo);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureRepoEventBuilder(RepoEvent.Builder<DataAttributes<RES>> builder, EventInfo eventInfo)
|
||||||
{
|
{
|
||||||
EventType eventType = getDerivedEvent();
|
EventType eventType = getDerivedEvent();
|
||||||
|
|
||||||
DataAttributes<RES> eventData = buildEventData(eventInfo, resource, eventType);
|
DataAttributes<RES> eventData = buildEventData(eventInfo, resource, eventType);
|
||||||
|
|
||||||
return RepoEvent.<DataAttributes<RES>>builder()
|
builder.setId(eventInfo.getId())
|
||||||
.setId(eventInfo.getId())
|
.setSource(eventInfo.getSource())
|
||||||
.setSource(eventInfo.getSource())
|
.setTime(eventInfo.getTimestamp())
|
||||||
.setTime(eventInfo.getTimestamp())
|
.setType(eventType.getType())
|
||||||
.setType(eventType.getType())
|
.setData(eventData)
|
||||||
.setData(eventData)
|
.setDataschema(EventJSONSchema.getSchemaV1(eventType));
|
||||||
.setDataschema(EventJSONSchema.getSchemaV1(eventType))
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,9 +124,9 @@ public abstract class EventConsolidator<REF extends EntityRef, RES extends Resou
|
|||||||
*/
|
*/
|
||||||
protected DataAttributes<RES> buildEventData(EventInfo eventInfo, RES resource, EventType eventType)
|
protected DataAttributes<RES> buildEventData(EventInfo eventInfo, RES resource, EventType eventType)
|
||||||
{
|
{
|
||||||
return EventData.<RES>builder()
|
return EventData.<RES> builder()
|
||||||
.setEventGroupId(eventInfo.getTxnId())
|
.setEventGroupId(eventInfo.getTxnId())
|
||||||
.setResource(resource)
|
.setResource(resource)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 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
|
||||||
@@ -125,6 +125,9 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
/** Number of (bytecode) instructions that will trigger the observer */
|
/** Number of (bytecode) instructions that will trigger the observer */
|
||||||
private int observerInstructionCount = 100;
|
private int observerInstructionCount = 100;
|
||||||
|
|
||||||
|
/** Flag to enable or disable scope cleaning at the end of each script execution */
|
||||||
|
private boolean cleanScope = true;
|
||||||
|
|
||||||
/** Custom context factory */
|
/** Custom context factory */
|
||||||
public static AlfrescoContextFactory contextFactory;
|
public static AlfrescoContextFactory contextFactory;
|
||||||
|
|
||||||
@@ -209,6 +212,15 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param cleanScope
|
||||||
|
* true to enable scope cleaning at the end of each script execution - set to false to disable this feature.
|
||||||
|
*/
|
||||||
|
public void setCleanScope(boolean cleanScope)
|
||||||
|
{
|
||||||
|
this.cleanScope = cleanScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* @see org.alfresco.service.cmr.repository.ScriptProcessor#reset()
|
* @see org.alfresco.service.cmr.repository.ScriptProcessor#reset()
|
||||||
*/
|
*/
|
||||||
public void reset()
|
public void reset()
|
||||||
@@ -614,7 +626,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (!secure)
|
if (!secure && cleanScope)
|
||||||
{
|
{
|
||||||
unsetScope(model, scope);
|
unsetScope(model, scope);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 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
|
||||||
@@ -23,239 +23,290 @@
|
|||||||
* 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.node.getchildren;
|
package org.alfresco.repo.node.getchildren;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.domain.node.NodeEntity;
|
import org.alfresco.repo.domain.node.AuditablePropertiesEntity;
|
||||||
import org.alfresco.repo.domain.node.NodePropertyEntity;
|
import org.alfresco.repo.domain.node.NodePropertyEntity;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
/**
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
* Filterable/Sortable Node Entity
|
|
||||||
*
|
/**
|
||||||
* Can be optionally filtered/sorted by (up to) three properties - note: sort properties are applied in order
|
* Filterable/Sortable Node Entity
|
||||||
*
|
*
|
||||||
* @author jan
|
* Can be optionally filtered/sorted by (up to) three properties - note: sort properties are applied in order
|
||||||
* @since 4.0
|
*
|
||||||
*/
|
* @author jan
|
||||||
public class FilterSortNodeEntity
|
* @since 4.0
|
||||||
{
|
*/
|
||||||
private Long id; // node id
|
public class FilterSortNodeEntity
|
||||||
|
{
|
||||||
private NodeEntity node;
|
private Long id; // node id
|
||||||
private NodePropertyEntity prop1;
|
private String nodeUuid;
|
||||||
private NodePropertyEntity prop2;
|
private Long typeQNameId;
|
||||||
private NodePropertyEntity prop3;
|
|
||||||
|
private AuditablePropertiesEntity auditablePropertiesEntity;
|
||||||
// Supplemental query-related parameters
|
private NodePropertyEntity prop1;
|
||||||
private Long parentNodeId;
|
private NodePropertyEntity prop2;
|
||||||
private Long prop1qnameId;
|
private NodePropertyEntity prop3;
|
||||||
private Long prop2qnameId;
|
|
||||||
private Long prop3qnameId;
|
private String storeProtocol;
|
||||||
private List<Long> childNodeTypeQNameIds;
|
private String storeIdentifier;
|
||||||
private Set<Long> assocTypeQNameIds;
|
|
||||||
private String pattern;
|
// Supplemental query-related parameters
|
||||||
private Long namePropertyQNameId;
|
private Long parentNodeId;
|
||||||
private boolean auditableProps;
|
private Long prop1qnameId;
|
||||||
private boolean nodeType;
|
private Long prop2qnameId;
|
||||||
|
private Long prop3qnameId;
|
||||||
private Boolean isPrimary;
|
private List<Long> childNodeTypeQNameIds;
|
||||||
|
private Set<Long> assocTypeQNameIds;
|
||||||
/**
|
private String pattern;
|
||||||
* Default constructor
|
private Long namePropertyQNameId;
|
||||||
*/
|
private boolean auditableProps;
|
||||||
public FilterSortNodeEntity()
|
private boolean nodeType;
|
||||||
{
|
|
||||||
auditableProps = false;
|
private Boolean isPrimary;
|
||||||
}
|
|
||||||
|
/**
|
||||||
public Long getId()
|
* Default constructor
|
||||||
{
|
*/
|
||||||
return id;
|
public FilterSortNodeEntity()
|
||||||
}
|
{
|
||||||
|
auditableProps = false;
|
||||||
public void setId(Long id)
|
}
|
||||||
{
|
|
||||||
this.id = id;
|
public Long getId()
|
||||||
}
|
{
|
||||||
|
return id;
|
||||||
public String getPattern()
|
}
|
||||||
{
|
|
||||||
return pattern;
|
public void setId(Long id)
|
||||||
}
|
{
|
||||||
|
this.id = id;
|
||||||
protected String escape(String s, char escapeChar)
|
}
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
public String getNodeUuid()
|
||||||
int idx = -1;
|
{
|
||||||
int offset = 0;
|
return nodeUuid;
|
||||||
do
|
}
|
||||||
{
|
|
||||||
idx = s.indexOf(escapeChar, offset);
|
public void setNodeUuid(String nodeUuid)
|
||||||
if(idx != -1)
|
{
|
||||||
{
|
this.nodeUuid = nodeUuid;
|
||||||
sb.append(s.substring(offset, idx));
|
}
|
||||||
sb.append("\\");
|
|
||||||
sb.append(escapeChar);
|
public Long getTypeQNameId()
|
||||||
offset = idx + 1;
|
{
|
||||||
}
|
return typeQNameId;
|
||||||
}
|
}
|
||||||
while(idx != -1);
|
|
||||||
sb.append(s.substring(offset));
|
public void setTypeQNameId(Long typeQNameId)
|
||||||
return sb.toString();
|
{
|
||||||
}
|
this.typeQNameId = typeQNameId;
|
||||||
|
}
|
||||||
public void setPattern(String pattern)
|
|
||||||
{
|
public String getPattern()
|
||||||
if(pattern != null)
|
{
|
||||||
{
|
return pattern;
|
||||||
// escape the '%' character with '\' (standard SQL escape character)
|
}
|
||||||
pattern = escape(pattern, '%');
|
|
||||||
// replace the wildcard character '*' with the one used in database queries i.e. '%'
|
protected String escape(String s, char escapeChar)
|
||||||
this.pattern = pattern.replace('*', '%');
|
{
|
||||||
}
|
StringBuilder sb = new StringBuilder();
|
||||||
}
|
int idx = -1;
|
||||||
|
int offset = 0;
|
||||||
public void setAssocTypeQNameIds(Set<Long> assocTypeQNameIds)
|
do
|
||||||
{
|
{
|
||||||
this.assocTypeQNameIds = assocTypeQNameIds;
|
idx = s.indexOf(escapeChar, offset);
|
||||||
}
|
if (idx != -1)
|
||||||
|
{
|
||||||
public Set<Long> getAssocTypeQNameIds()
|
sb.append(s.substring(offset, idx));
|
||||||
{
|
sb.append("\\");
|
||||||
return assocTypeQNameIds;
|
sb.append(escapeChar);
|
||||||
}
|
offset = idx + 1;
|
||||||
|
}
|
||||||
public Long getNamePropertyQNameId()
|
} while (idx != -1);
|
||||||
{
|
sb.append(s.substring(offset));
|
||||||
return namePropertyQNameId;
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNamePropertyQNameId(Long namePropertyQNameId)
|
public void setPattern(String pattern)
|
||||||
{
|
{
|
||||||
this.namePropertyQNameId = namePropertyQNameId;
|
if (pattern != null)
|
||||||
}
|
{
|
||||||
|
// escape the '%' character with '\' (standard SQL escape character)
|
||||||
public NodePropertyEntity getProp1()
|
pattern = escape(pattern, '%');
|
||||||
{
|
// replace the wildcard character '*' with the one used in database queries i.e. '%'
|
||||||
return prop1;
|
this.pattern = pattern.replace('*', '%');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public void setProp1(NodePropertyEntity prop1)
|
|
||||||
{
|
public void setAssocTypeQNameIds(Set<Long> assocTypeQNameIds)
|
||||||
this.prop1 = prop1;
|
{
|
||||||
}
|
this.assocTypeQNameIds = assocTypeQNameIds;
|
||||||
|
}
|
||||||
public NodePropertyEntity getProp2()
|
|
||||||
{
|
public Set<Long> getAssocTypeQNameIds()
|
||||||
return prop2;
|
{
|
||||||
}
|
return assocTypeQNameIds;
|
||||||
|
}
|
||||||
public void setProp2(NodePropertyEntity prop2)
|
|
||||||
{
|
public Long getNamePropertyQNameId()
|
||||||
this.prop2 = prop2;
|
{
|
||||||
}
|
return namePropertyQNameId;
|
||||||
|
}
|
||||||
public NodePropertyEntity getProp3()
|
|
||||||
{
|
public void setNamePropertyQNameId(Long namePropertyQNameId)
|
||||||
return prop3;
|
{
|
||||||
}
|
this.namePropertyQNameId = namePropertyQNameId;
|
||||||
|
}
|
||||||
public void setProp3(NodePropertyEntity prop3)
|
|
||||||
{
|
public AuditablePropertiesEntity getAuditablePropertiesEntity()
|
||||||
this.prop3 = prop3;
|
{
|
||||||
}
|
return auditablePropertiesEntity;
|
||||||
|
}
|
||||||
public NodeEntity getNode()
|
|
||||||
{
|
public void setAuditablePropertiesEntity(AuditablePropertiesEntity auditablePropertiesEntity)
|
||||||
return node;
|
{
|
||||||
}
|
this.auditablePropertiesEntity = auditablePropertiesEntity;
|
||||||
|
}
|
||||||
public void setNode(NodeEntity childNode)
|
|
||||||
{
|
public NodePropertyEntity getProp1()
|
||||||
this.node = childNode;
|
{
|
||||||
}
|
return prop1;
|
||||||
|
}
|
||||||
// Supplemental query-related parameters
|
|
||||||
|
public void setProp1(NodePropertyEntity prop1)
|
||||||
public Long getParentNodeId()
|
{
|
||||||
{
|
this.prop1 = prop1;
|
||||||
return parentNodeId;
|
}
|
||||||
}
|
|
||||||
|
public NodePropertyEntity getProp2()
|
||||||
public void setParentNodeId(Long parentNodeId)
|
{
|
||||||
{
|
return prop2;
|
||||||
this.parentNodeId = parentNodeId;
|
}
|
||||||
}
|
|
||||||
|
public void setProp2(NodePropertyEntity prop2)
|
||||||
public Long getProp1qnameId()
|
{
|
||||||
{
|
this.prop2 = prop2;
|
||||||
return prop1qnameId;
|
}
|
||||||
}
|
|
||||||
|
public NodePropertyEntity getProp3()
|
||||||
public void setProp1qnameId(Long prop1qnameId)
|
{
|
||||||
{
|
return prop3;
|
||||||
this.prop1qnameId = prop1qnameId;
|
}
|
||||||
}
|
|
||||||
|
public void setProp3(NodePropertyEntity prop3)
|
||||||
public Long getProp2qnameId()
|
{
|
||||||
{
|
this.prop3 = prop3;
|
||||||
return prop2qnameId;
|
}
|
||||||
}
|
|
||||||
|
public String getStoreProtocol()
|
||||||
public void setProp2qnameId(Long prop2qnameId)
|
{
|
||||||
{
|
return storeProtocol;
|
||||||
this.prop2qnameId = prop2qnameId;
|
}
|
||||||
}
|
|
||||||
|
public void setStoreProtocol(String storeProtocol)
|
||||||
public Long getProp3qnameId()
|
{
|
||||||
{
|
this.storeProtocol = storeProtocol;
|
||||||
return prop3qnameId;
|
}
|
||||||
}
|
|
||||||
|
public String getStoreIdentifier()
|
||||||
public void setProp3qnameId(Long prop3qnameId)
|
{
|
||||||
{
|
return storeIdentifier;
|
||||||
this.prop3qnameId = prop3qnameId;
|
}
|
||||||
}
|
|
||||||
|
public void setStoreIdentifier(String storeIdentifier)
|
||||||
public List<Long> getChildNodeTypeQNameIds()
|
{
|
||||||
{
|
this.storeIdentifier = storeIdentifier;
|
||||||
return childNodeTypeQNameIds;
|
}
|
||||||
}
|
|
||||||
|
// Supplemental query-related parameters
|
||||||
public void setChildNodeTypeQNameIds(List<Long> childNodeTypeQNameIds)
|
|
||||||
{
|
public Long getParentNodeId()
|
||||||
this.childNodeTypeQNameIds = childNodeTypeQNameIds;
|
{
|
||||||
}
|
return parentNodeId;
|
||||||
|
}
|
||||||
public boolean isAuditableProps()
|
|
||||||
{
|
public void setParentNodeId(Long parentNodeId)
|
||||||
return auditableProps;
|
{
|
||||||
}
|
this.parentNodeId = parentNodeId;
|
||||||
|
}
|
||||||
public void setAuditableProps(boolean auditableProps)
|
|
||||||
{
|
public Long getProp1qnameId()
|
||||||
this.auditableProps = auditableProps;
|
{
|
||||||
}
|
return prop1qnameId;
|
||||||
|
}
|
||||||
public boolean isNodeType()
|
|
||||||
{
|
public void setProp1qnameId(Long prop1qnameId)
|
||||||
return nodeType;
|
{
|
||||||
}
|
this.prop1qnameId = prop1qnameId;
|
||||||
|
}
|
||||||
public void setNodeType(boolean nodeType)
|
|
||||||
{
|
public Long getProp2qnameId()
|
||||||
this.nodeType = nodeType;
|
{
|
||||||
}
|
return prop2qnameId;
|
||||||
|
}
|
||||||
public Boolean isPrimary()
|
|
||||||
{
|
public void setProp2qnameId(Long prop2qnameId)
|
||||||
return isPrimary;
|
{
|
||||||
}
|
this.prop2qnameId = prop2qnameId;
|
||||||
|
}
|
||||||
public void setIsPrimary(Boolean isPrimary)
|
|
||||||
{
|
public Long getProp3qnameId()
|
||||||
this.isPrimary = isPrimary;
|
{
|
||||||
}
|
return prop3qnameId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setProp3qnameId(Long prop3qnameId)
|
||||||
|
{
|
||||||
|
this.prop3qnameId = prop3qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getChildNodeTypeQNameIds()
|
||||||
|
{
|
||||||
|
return childNodeTypeQNameIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildNodeTypeQNameIds(List<Long> childNodeTypeQNameIds)
|
||||||
|
{
|
||||||
|
this.childNodeTypeQNameIds = childNodeTypeQNameIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuditableProps()
|
||||||
|
{
|
||||||
|
return auditableProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuditableProps(boolean auditableProps)
|
||||||
|
{
|
||||||
|
this.auditableProps = auditableProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNodeType()
|
||||||
|
{
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodeType(boolean nodeType)
|
||||||
|
{
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPrimary()
|
||||||
|
{
|
||||||
|
return isPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsPrimary(Boolean isPrimary)
|
||||||
|
{
|
||||||
|
this.isPrimary = isPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeRef createNodeRef()
|
||||||
|
{
|
||||||
|
return new NodeRef(new StoreRef(storeProtocol, storeIdentifier), nodeUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -81,11 +81,19 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
|
|
||||||
public static final QName DEFAULT_RENDITION_CONTENT_PROP = ContentModel.PROP_CONTENT;
|
public static final QName DEFAULT_RENDITION_CONTENT_PROP = ContentModel.PROP_CONTENT;
|
||||||
public static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
public static final String DEFAULT_MIMETYPE = MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
||||||
|
public static final String MIMETYPE_METADATA_EXTRACT = "alfresco-metadata-extract";
|
||||||
|
public static final String MIMETYPE_METADATA_EMBED = "alfresco-metadata-embed";
|
||||||
public static final String DEFAULT_ENCODING = "UTF-8";
|
public static final String DEFAULT_ENCODING = "UTF-8";
|
||||||
|
|
||||||
public static final int SOURCE_HAS_NO_CONTENT = -1;
|
public static final int SOURCE_HAS_NO_CONTENT = -1;
|
||||||
public static final int RENDITION2_DOES_NOT_EXIST = -2;
|
public static final int RENDITION2_DOES_NOT_EXIST = -2;
|
||||||
|
|
||||||
|
// Allowed mimetypes to support text or metadata extract transforms when thumbnails are disabled.
|
||||||
|
private static final Set<String> ALLOWED_MIMETYPES = Set.of(
|
||||||
|
MimetypeMap.MIMETYPE_TEXT_PLAIN,
|
||||||
|
MIMETYPE_METADATA_EXTRACT,
|
||||||
|
MIMETYPE_METADATA_EMBED);
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(RenditionService2Impl.class);
|
private static Log logger = LogFactory.getLog(RenditionService2Impl.class);
|
||||||
|
|
||||||
// As Async transforms and renditions are so similar, this class provides a way to provide the code that is different.
|
// As Async transforms and renditions are so similar, this class provides a way to provide the code that is different.
|
||||||
@@ -288,7 +296,7 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!isEnabled())
|
if (!isAsyncAllowed(renderOrTransform))
|
||||||
{
|
{
|
||||||
throw new RenditionService2Exception("Async transforms and renditions are disabled " +
|
throw new RenditionService2Exception("Async transforms and renditions are disabled " +
|
||||||
"(system.thumbnail.generate=false or renditionService2.enabled=false).");
|
"(system.thumbnail.generate=false or renditionService2.enabled=false).");
|
||||||
@@ -967,4 +975,23 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if the given transform callback is a text extract transform for content indexing or metadata extract/embed.
|
||||||
|
private boolean isTextOrMetadataExtractTransform(RenderOrTransformCallBack renderOrTransform)
|
||||||
|
{
|
||||||
|
RenditionDefinition2 renditionDefinition = renderOrTransform.getRenditionDefinition();
|
||||||
|
return renditionDefinition != null && ALLOWED_MIMETYPES.contains(renditionDefinition.getTargetMimetype());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAsyncAllowed(RenderOrTransformCallBack renderOrTransform)
|
||||||
|
{
|
||||||
|
// If enabled is false, all async transforms/renditions must be blocked
|
||||||
|
if (!enabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If thumbnails are disabled, allow only text extract or metadata extract/embed transforms
|
||||||
|
return thumbnailsEnabled || isTextOrMetadataExtractTransform(renderOrTransform);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ import com.nimbusds.oauth2.sdk.id.Identifier;
|
|||||||
import com.nimbusds.oauth2.sdk.id.Issuer;
|
import com.nimbusds.oauth2.sdk.id.Issuer;
|
||||||
import com.nimbusds.openid.connect.sdk.claims.PersonClaims;
|
import com.nimbusds.openid.connect.sdk.claims.PersonClaims;
|
||||||
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
|
import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
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.apache.hc.client5.http.classic.HttpClient;
|
import org.apache.hc.client5.http.classic.HttpClient;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import com.nimbusds.oauth2.sdk.Scope;
|
import com.nimbusds.oauth2.sdk.Scope;
|
||||||
import com.nimbusds.oauth2.sdk.id.Identifier;
|
import com.nimbusds.oauth2.sdk.id.Identifier;
|
||||||
import com.nimbusds.oauth2.sdk.id.State;
|
import com.nimbusds.oauth2.sdk.id.State;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
|
|||||||
@@ -133,7 +133,15 @@
|
|||||||
<resultMap id="result_FilterSortNode" type="FilterSortNode">
|
<resultMap id="result_FilterSortNode" type="FilterSortNode">
|
||||||
|
|
||||||
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
<result property="nodeUuid" column="uuid" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="typeQNameId" column="type_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
|
|
||||||
|
<result property="auditablePropertiesEntity.auditCreator" column="audit_creator" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="auditablePropertiesEntity.auditCreated" column="audit_created" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="auditablePropertiesEntity.auditModifier" column="audit_modifier" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="auditablePropertiesEntity.auditModified" column="audit_modified" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="auditablePropertiesEntity.auditAccessed" column="audit_accessed" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
|
||||||
<result property="prop1.nodeId" column="prop1_node_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="prop1.nodeId" column="prop1_node_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="prop1.key.qnameId" column="prop1_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="prop1.key.qnameId" column="prop1_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="prop1.key.localeId" column="prop1_locale_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<result property="prop1.key.localeId" column="prop1_locale_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
@@ -169,8 +177,9 @@
|
|||||||
<result property="prop3.value.floatValue" column="prop3_float_value" jdbcType="FLOAT" javaType="java.lang.Float"/>
|
<result property="prop3.value.floatValue" column="prop3_float_value" jdbcType="FLOAT" javaType="java.lang.Float"/>
|
||||||
<result property="prop3.value.doubleValue" column="prop3_double_value" jdbcType="FLOAT" javaType="java.lang.Double"/>
|
<result property="prop3.value.doubleValue" column="prop3_double_value" jdbcType="FLOAT" javaType="java.lang.Double"/>
|
||||||
<result property="prop3.value.stringValue" column="prop3_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
<result property="prop3.value.stringValue" column="prop3_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
|
||||||
<association property="node" resultMap="alfresco.node.result_Node"/>
|
<result property="storeProtocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
<result property="storeIdentifier" column="identifier" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
|
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
@@ -782,25 +791,6 @@
|
|||||||
<if test="ordered == true">order by node.id ASC</if>
|
<if test="ordered == true">order by node.id ASC</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="select_NodesWithAspectIds_Limited" parameterType="Ids" resultMap="result_NodeRef" >
|
|
||||||
select
|
|
||||||
node.id as id,
|
|
||||||
store.protocol as protocol,
|
|
||||||
store.identifier as identifier,
|
|
||||||
node.uuid as uuid
|
|
||||||
from
|
|
||||||
alf_node_aspects na
|
|
||||||
join alf_node node on (na.node_id = node.id)
|
|
||||||
left join alf_store store on (store.id = node.store_id)
|
|
||||||
where
|
|
||||||
<![CDATA[na.node_id >= #{idOne}]]>
|
|
||||||
<if test="idTwo != null"><![CDATA[and na.node_id < #{idTwo}]]></if>
|
|
||||||
and na.qname_id in
|
|
||||||
<foreach item="item" index="i" collection="ids" open="(" separator="," close=")">#{item}</foreach>
|
|
||||||
<if test="ordered == true">order by node.id ASC</if>
|
|
||||||
<if test="maxResults != null"><![CDATA[limit #{maxResults}]]></if>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<!-- Common results for result_NodeAssoc -->
|
<!-- Common results for result_NodeAssoc -->
|
||||||
<sql id="select_NodeAssoc_Results">
|
<sql id="select_NodeAssoc_Results">
|
||||||
select
|
select
|
||||||
@@ -991,8 +981,8 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- GetChildren - with explicit prop filtering and/or sorting -->
|
<!-- GetChildren - with explicit prop filtering and/or sorting -->
|
||||||
<select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode">
|
<select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode" flushCache="true">
|
||||||
select
|
select distinct
|
||||||
childNode.id as id,
|
childNode.id as id,
|
||||||
childNode.version as version,
|
childNode.version as version,
|
||||||
childStore.id as store_id,
|
childStore.id as store_id,
|
||||||
@@ -1008,7 +998,7 @@
|
|||||||
childNode.audit_created as audit_created,
|
childNode.audit_created as audit_created,
|
||||||
childNode.audit_modifier as audit_modifier,
|
childNode.audit_modifier as audit_modifier,
|
||||||
childNode.audit_modified as audit_modified,
|
childNode.audit_modified as audit_modified,
|
||||||
childNode.audit_accessed as audit_accessed
|
childNode.audit_accessed as audit_accessed
|
||||||
<if test="prop1qnameId != null">
|
<if test="prop1qnameId != null">
|
||||||
, prop1.node_id as prop1_node_id,
|
, prop1.node_id as prop1_node_id,
|
||||||
prop1.qname_id as prop1_qname_id,
|
prop1.qname_id as prop1_qname_id,
|
||||||
@@ -1086,9 +1076,6 @@
|
|||||||
#{item}
|
#{item}
|
||||||
</foreach>
|
</foreach>
|
||||||
</if>
|
</if>
|
||||||
<if test="prop1qnameId == null and auditableProps == false">
|
|
||||||
<include refid="alfresco.node.select_ChildAssoc_OrderBy"/>
|
|
||||||
</if>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- GetChildren - with no explicit sorting (or prop filtering) - note: still filtered by child type (and optionally primary or secondary) -->
|
<!-- GetChildren - with no explicit sorting (or prop filtering) - note: still filtered by child type (and optionally primary or secondary) -->
|
||||||
@@ -1566,4 +1553,4 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -30,4 +30,23 @@
|
|||||||
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
|
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
<select id="select_NodesWithAspectIds_Limited" parameterType="Ids" resultMap="alfresco.node.result_NodeRef" >
|
||||||
|
select
|
||||||
|
node.id as id,
|
||||||
|
store.protocol as protocol,
|
||||||
|
store.identifier as identifier,
|
||||||
|
node.uuid as uuid
|
||||||
|
from
|
||||||
|
alf_node_aspects na
|
||||||
|
join alf_node node on (na.node_id = node.id)
|
||||||
|
left join alf_store store on (store.id = node.store_id)
|
||||||
|
where
|
||||||
|
<![CDATA[na.node_id >= #{idOne}]]>
|
||||||
|
<if test="idTwo != null"><![CDATA[and na.node_id < #{idTwo}]]></if>
|
||||||
|
and na.qname_id in
|
||||||
|
<foreach item="item" index="i" collection="ids" open="(" separator="," close=")">#{item}</foreach>
|
||||||
|
<if test="ordered == true">order by node.id ASC</if>
|
||||||
|
<if test="maxResults != null"><![CDATA[limit #{maxResults}]]></if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|||||||
@@ -30,4 +30,23 @@
|
|||||||
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
|
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
<select id="select_NodesWithAspectIds_Limited" parameterType="Ids" resultMap="alfresco.node.result_NodeRef" >
|
||||||
|
select
|
||||||
|
node.id as id,
|
||||||
|
store.protocol as protocol,
|
||||||
|
store.identifier as identifier,
|
||||||
|
node.uuid as uuid
|
||||||
|
from
|
||||||
|
alf_node_aspects na
|
||||||
|
join alf_node node on (na.node_id = node.id)
|
||||||
|
left join alf_store store on (store.id = node.store_id)
|
||||||
|
where
|
||||||
|
<![CDATA[na.node_id >= #{idOne}]]>
|
||||||
|
<if test="idTwo != null"><![CDATA[and na.node_id < #{idTwo}]]></if>
|
||||||
|
and na.qname_id in
|
||||||
|
<foreach item="item" index="i" collection="ids" open="(" separator="," close=")">#{item}</foreach>
|
||||||
|
<if test="ordered == true">order by node.id ASC</if>
|
||||||
|
<if test="maxResults != null"><![CDATA[limit #{maxResults}]]></if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
repository.name=Main Repository
|
repository.name=Main Repository
|
||||||
|
|
||||||
# Schema number
|
# Schema number
|
||||||
version.schema=19500
|
version.schema=19600
|
||||||
|
|
||||||
# Directory configuration
|
# Directory configuration
|
||||||
|
|
||||||
@@ -1394,6 +1394,9 @@ scripts.execution.maxMemoryUsedInBytes=-1
|
|||||||
# Number of instructions that will trigger the observer
|
# Number of instructions that will trigger the observer
|
||||||
scripts.execution.observerInstructionCount=5000
|
scripts.execution.observerInstructionCount=5000
|
||||||
|
|
||||||
|
# Flag to control if the scope is cleaned at the end of script execution
|
||||||
|
scripts.execution.clean.scope=true
|
||||||
|
|
||||||
# Default value being used in POST/size-details endpoint to partition a huge folder into smaller chunks
|
# Default value being used in POST/size-details endpoint to partition a huge folder into smaller chunks
|
||||||
# so that we can compute more efficiently and consolidate all sizes into a single unit.
|
# so that we can compute more efficiently and consolidate all sizes into a single unit.
|
||||||
default.async.folder.items=1000
|
default.async.folder.items=1000
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
<property name="observerInstructionCount">
|
<property name="observerInstructionCount">
|
||||||
<value>${scripts.execution.observerInstructionCount}</value>
|
<value>${scripts.execution.observerInstructionCount}</value>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="cleanScope">
|
||||||
|
<value>${scripts.execution.clean.scope}</value>
|
||||||
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- base config implementation that script extension beans extend from - for auto registration
|
<!-- base config implementation that script extension beans extend from - for auto registration
|
||||||
|
|||||||
@@ -26,6 +26,12 @@
|
|||||||
|
|
||||||
package org.alfresco.repo.event2;
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.alfresco.model.ContentModel.PROP_DESCRIPTION;
|
import static org.alfresco.model.ContentModel.PROP_DESCRIPTION;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -35,6 +41,9 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
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.M2Model;
|
import org.alfresco.repo.dictionary.M2Model;
|
||||||
@@ -53,7 +62,6 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Iulian Aftene
|
* @author Iulian Aftene
|
||||||
@@ -66,20 +74,20 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
public void testUpdateNodeResourceContent()
|
public void testUpdateNodeResourceContent()
|
||||||
{
|
{
|
||||||
ContentService contentService = (ContentService) applicationContext.getBean(
|
ContentService contentService = (ContentService) applicationContext.getBean(
|
||||||
"contentService");
|
"contentService");
|
||||||
|
|
||||||
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||||
|
|
||||||
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
||||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(),
|
||||||
resultRepoEvent.getType());
|
resultRepoEvent.getType());
|
||||||
|
|
||||||
NodeResource resource = getNodeResource(resultRepoEvent);
|
NodeResource resource = getNodeResource(resultRepoEvent);
|
||||||
assertNull("Content should have been null.", resource.getContent());
|
assertNull("Content should have been null.", resource.getContent());
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
||||||
true);
|
true);
|
||||||
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
||||||
writer.setEncoding("UTF-8");
|
writer.setEncoding("UTF-8");
|
||||||
writer.putContent("test content.");
|
writer.putContent("test content.");
|
||||||
@@ -90,7 +98,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
|
|
||||||
resultRepoEvent = getRepoEvent(2);
|
resultRepoEvent = getRepoEvent(2);
|
||||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||||
resultRepoEvent.getType());
|
resultRepoEvent.getType());
|
||||||
|
|
||||||
resource = getNodeResource(resultRepoEvent);
|
resource = getNodeResource(resultRepoEvent);
|
||||||
ContentInfo content = resource.getContent();
|
ContentInfo content = resource.getContent();
|
||||||
@@ -105,7 +113,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
// Update the content again
|
// Update the content again
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.TYPE_CONTENT,
|
||||||
true);
|
true);
|
||||||
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
writer.setMimetype(MimetypeMap.MIMETYPE_PDF);
|
||||||
writer.setEncoding("UTF-8");
|
writer.setEncoding("UTF-8");
|
||||||
writer.putContent("A quick brown fox jumps over the lazy dog.");
|
writer.putContent("A quick brown fox jumps over the lazy dog.");
|
||||||
@@ -370,7 +378,6 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals("new test title", title);
|
assertEquals("new test title", title);
|
||||||
assertEquals("new test title", getLocalizedProperty(resource, "cm:title", defaultLocale));
|
assertEquals("new test title", getLocalizedProperty(resource, "cm:title", defaultLocale));
|
||||||
|
|
||||||
|
|
||||||
resourceBefore = getNodeResourceBefore(3);
|
resourceBefore = getNodeResourceBefore(3);
|
||||||
title = getProperty(resourceBefore, "cm:title");
|
title = getProperty(resourceBefore, "cm:title");
|
||||||
assertEquals("Wrong old property.", "test title", title);
|
assertEquals("Wrong old property.", "test title", title);
|
||||||
@@ -490,14 +497,14 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
resource = getNodeResource(2);
|
resource = getNodeResource(2);
|
||||||
assertNotNull(resource.getAspectNames());
|
assertNotNull(resource.getAspectNames());
|
||||||
assertTrue(resource.getAspectNames().contains("cm:versionable"));
|
assertTrue(resource.getAspectNames().contains("cm:versionable"));
|
||||||
//Check all aspects
|
// Check all aspects
|
||||||
Set<String> expectedAspects = new HashSet<>(originalAspects);
|
Set<String> expectedAspects = new HashSet<>(originalAspects);
|
||||||
expectedAspects.add("cm:versionable");
|
expectedAspects.add("cm:versionable");
|
||||||
assertEquals(expectedAspects, resource.getAspectNames());
|
assertEquals(expectedAspects, resource.getAspectNames());
|
||||||
// Check properties
|
// Check properties
|
||||||
assertFalse(resource.getProperties().isEmpty());
|
assertFalse(resource.getProperties().isEmpty());
|
||||||
|
|
||||||
//Check resourceBefore
|
// Check resourceBefore
|
||||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||||
assertNotNull(resourceBefore.getAspectNames());
|
assertNotNull(resourceBefore.getAspectNames());
|
||||||
assertEquals(originalAspects, resourceBefore.getAspectNames());
|
assertEquals(originalAspects, resourceBefore.getAspectNames());
|
||||||
@@ -544,21 +551,64 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames());
|
assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveAspectPropertiesTest()
|
||||||
|
{
|
||||||
|
final NodeRef nodeRef = createNode(ContentModel.TYPE_CONTENT);
|
||||||
|
NodeResource resource = getNodeResource(1);
|
||||||
|
final Set<String> originalAspects = resource.getAspectNames();
|
||||||
|
assertNotNull(originalAspects);
|
||||||
|
|
||||||
|
// Add cm:geographic aspect with properties
|
||||||
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
|
Map<QName, Serializable> aspectProperties = new HashMap<>();
|
||||||
|
aspectProperties.put(ContentModel.PROP_LATITUDE, "12.345678");
|
||||||
|
aspectProperties.put(ContentModel.PROP_LONGITUDE, "12.345678");
|
||||||
|
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, aspectProperties);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
resource = getNodeResource(2);
|
||||||
|
Set<String> aspectsBeforeRemove = resource.getAspectNames();
|
||||||
|
assertNotNull(aspectsBeforeRemove);
|
||||||
|
assertTrue(aspectsBeforeRemove.contains("cm:geographic"));
|
||||||
|
|
||||||
|
// Remove cm:geographic aspect - this automatically removes the properties from the node
|
||||||
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
|
nodeService.removeAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
resource = getNodeResource(3);
|
||||||
|
assertEquals(originalAspects, resource.getAspectNames());
|
||||||
|
|
||||||
|
NodeResource resourceBefore = getNodeResourceBefore(3);
|
||||||
|
assertNotNull(resourceBefore.getAspectNames());
|
||||||
|
assertEquals(aspectsBeforeRemove, resourceBefore.getAspectNames());
|
||||||
|
// Resource before should contain cm:latitude and cm:longitude properties
|
||||||
|
assertNotNull(resourceBefore.getProperties());
|
||||||
|
assertTrue(resourceBefore.getProperties().containsKey("cm:latitude"));
|
||||||
|
assertTrue(resourceBefore.getProperties().containsKey("cm:longitude"));
|
||||||
|
// Resource after should NOT contain cm:latitude and cm:longitude properties
|
||||||
|
assertNotNull(resource.getProperties());
|
||||||
|
assertFalse(resource.getProperties().containsKey("cm:latitude"));
|
||||||
|
assertFalse(resource.getProperties().containsKey("cm:longitude"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateAndUpdateInTheSameTransaction()
|
public void testCreateAndUpdateInTheSameTransaction()
|
||||||
{
|
{
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
|
|
||||||
NodeRef node1 = nodeService.createNode(
|
NodeRef node1 = nodeService.createNode(
|
||||||
rootNodeRef,
|
rootNodeRef,
|
||||||
ContentModel.ASSOC_CHILDREN,
|
ContentModel.ASSOC_CHILDREN,
|
||||||
QName.createQName(TEST_NAMESPACE, GUID.generate()),
|
QName.createQName(TEST_NAMESPACE, GUID.generate()),
|
||||||
ContentModel.TYPE_CONTENT).getChildRef();
|
ContentModel.TYPE_CONTENT).getChildRef();
|
||||||
|
|
||||||
nodeService.setProperty(node1, PROP_DESCRIPTION, "test description");
|
nodeService.setProperty(node1, PROP_DESCRIPTION, "test description");
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
//Create and update node are done in the same transaction so one event is expected
|
// Create and update node are done in the same transaction so one event is expected
|
||||||
// to be generated
|
// to be generated
|
||||||
checkNumOfEvents(1);
|
checkNumOfEvents(1);
|
||||||
}
|
}
|
||||||
@@ -593,8 +643,8 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
||||||
|
|
||||||
NodeResource resourceBefore = getNodeResourceBefore(2);
|
NodeResource resourceBefore = getNodeResourceBefore(2);
|
||||||
assertEquals("Incorrect node type was found","cm:content", resourceBefore.getNodeType());
|
assertEquals("Incorrect node type was found", "cm:content", resourceBefore.getNodeType());
|
||||||
// assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed
|
// assertNotNull(resourceBefore.getModifiedAt()); uncomment this when the issue will be fixed
|
||||||
assertNull(resourceBefore.getId());
|
assertNull(resourceBefore.getId());
|
||||||
assertNull(resourceBefore.getContent());
|
assertNull(resourceBefore.getContent());
|
||||||
assertNull(resourceBefore.isFile());
|
assertNull(resourceBefore.isFile());
|
||||||
@@ -624,8 +674,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
m2Type.setTitle("Test type title");
|
m2Type.setTitle("Test type title");
|
||||||
|
|
||||||
// Create active model
|
// Create active model
|
||||||
CustomModelDefinition modelDefinition =
|
CustomModelDefinition modelDefinition = retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
|
||||||
retryingTransactionHelper.doInTransaction(() -> customModelService.createCustomModel(model, true));
|
|
||||||
|
|
||||||
assertNotNull(modelDefinition);
|
assertNotNull(modelDefinition);
|
||||||
assertEquals(modelName, modelDefinition.getName().getLocalName());
|
assertEquals(modelName, modelDefinition.getName().getLocalName());
|
||||||
@@ -655,7 +704,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||||
assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType());
|
assertEquals("cm:content node type was not found", "cm:content", nodeResource.getNodeType());
|
||||||
|
|
||||||
QName typeQName = QName.createQName("{" + namespacePair.getFirst()+ "}" + typeName);
|
QName typeQName = QName.createQName("{" + namespacePair.getFirst() + "}" + typeName);
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
nodeService.setType(nodeRef, typeQName);
|
nodeService.setType(nodeRef, typeQName);
|
||||||
|
|
||||||
@@ -757,7 +806,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
// we should have only 1 event, node.Created
|
// we should have only 1 event, node.Created
|
||||||
checkNumOfEvents(1);
|
checkNumOfEvents(1);
|
||||||
|
|
||||||
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
RepoEvent<EventData<NodeResource>> resultRepoEvent = getRepoEvent(1);
|
||||||
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
assertEquals("Wrong repo event type.", EventType.NODE_CREATED.getType(), resultRepoEvent.getType());
|
||||||
NodeResource nodeResource = getNodeResource(resultRepoEvent);
|
NodeResource nodeResource = getNodeResource(resultRepoEvent);
|
||||||
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
assertEquals("Incorrect node type was found", "cm:folder", nodeResource.getNodeType());
|
||||||
@@ -783,10 +832,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
moveFile,
|
moveFile,
|
||||||
folder2,
|
folder2,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -801,7 +850,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals("Wrong node parent.", folder1ID, moveFileParentBeforeMove);
|
assertEquals("Wrong node parent.", folder1ID, moveFileParentBeforeMove);
|
||||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||||
getRepoEvent(4).getType());
|
getRepoEvent(4).getType());
|
||||||
|
|
||||||
assertNull(resourceBefore.getId());
|
assertNull(resourceBefore.getId());
|
||||||
assertNull(resourceBefore.getName());
|
assertNull(resourceBefore.getName());
|
||||||
@@ -833,10 +882,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
moveFolder,
|
moveFolder,
|
||||||
grandParent,
|
grandParent,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -845,15 +894,13 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
final String grandParentID = getNodeResource(1).getId();
|
final String grandParentID = getNodeResource(1).getId();
|
||||||
final String parentID = getNodeResource(2).getId();
|
final String parentID = getNodeResource(2).getId();
|
||||||
|
|
||||||
final String moveFolderParentBeforeMove =
|
final String moveFolderParentBeforeMove = getNodeResourceBefore(4).getPrimaryHierarchy().get(0);
|
||||||
getNodeResourceBefore(4).getPrimaryHierarchy().get(0);
|
final String moveFolderParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||||
final String moveFolderParentAfterMove =
|
|
||||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
|
||||||
|
|
||||||
assertEquals("Wrong node parent.", parentID, moveFolderParentBeforeMove);
|
assertEquals("Wrong node parent.", parentID, moveFolderParentBeforeMove);
|
||||||
assertEquals("Wrong node parent.", grandParentID, moveFolderParentAfterMove);
|
assertEquals("Wrong node parent.", grandParentID, moveFolderParentAfterMove);
|
||||||
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
assertEquals("Wrong repo event type.", EventType.NODE_UPDATED.getType(),
|
||||||
getRepoEventWithoutWait(4).getType());
|
getRepoEventWithoutWait(4).getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -867,28 +914,25 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
grandParent,
|
grandParent,
|
||||||
root2,
|
root2,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
checkNumOfEvents(6);
|
checkNumOfEvents(6);
|
||||||
|
|
||||||
final String root2ID = getNodeResource(2).getId();
|
final String root2ID = getNodeResource(2).getId();
|
||||||
final String grandParentParentAfterMove =
|
final String grandParentParentAfterMove = getNodeResource(6).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(6).getPrimaryHierarchy().get(0);
|
|
||||||
assertEquals("Wrong node parent.", root2ID, grandParentParentAfterMove);
|
assertEquals("Wrong node parent.", root2ID, grandParentParentAfterMove);
|
||||||
|
|
||||||
final String grandParentID = getNodeResource(3).getId();
|
final String grandParentID = getNodeResource(3).getId();
|
||||||
final String parentIDOfTheParentFolder =
|
final String parentIDOfTheParentFolder = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
|
||||||
assertEquals("Wrong node parent.", grandParentID, parentIDOfTheParentFolder);
|
assertEquals("Wrong node parent.", grandParentID, parentIDOfTheParentFolder);
|
||||||
|
|
||||||
final String parentID = getNodeResource(4).getId();
|
final String parentID = getNodeResource(4).getId();
|
||||||
final String contentParentID =
|
final String contentParentID = getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(5).getPrimaryHierarchy().get(0);
|
|
||||||
assertEquals("Wrong node parent.", parentID, contentParentID);
|
assertEquals("Wrong node parent.", parentID, contentParentID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,10 +950,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
moveFile,
|
moveFile,
|
||||||
folder2,
|
folder2,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -918,8 +962,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertTrue("Wrong aspect.", resource.getAspectNames().contains("cm:versionable"));
|
assertTrue("Wrong aspect.", resource.getAspectNames().contains("cm:versionable"));
|
||||||
|
|
||||||
final String folder2ID = getNodeResource(2).getId();
|
final String folder2ID = getNodeResource(2).getId();
|
||||||
final String moveFileParentAfterMove =
|
final String moveFileParentAfterMove = getNodeResource(5).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(5).getPrimaryHierarchy().get(0);
|
|
||||||
|
|
||||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||||
}
|
}
|
||||||
@@ -935,10 +978,10 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
nodeService.setProperty(moveFile, ContentModel.PROP_NAME, "test_new_name");
|
nodeService.setProperty(moveFile, ContentModel.PROP_NAME, "test_new_name");
|
||||||
|
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
moveFile,
|
moveFile,
|
||||||
folder2,
|
folder2,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -946,8 +989,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
assertEquals("test_new_name", resource.getName());
|
assertEquals("test_new_name", resource.getName());
|
||||||
|
|
||||||
final String folder2ID = getNodeResource(2).getId();
|
final String folder2ID = getNodeResource(2).getId();
|
||||||
final String moveFileParentAfterMove =
|
final String moveFileParentAfterMove = getNodeResource(4).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(4).getPrimaryHierarchy().get(0);
|
|
||||||
|
|
||||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||||
}
|
}
|
||||||
@@ -958,28 +1000,28 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
|
|
||||||
NodeRef folder1 = nodeService.createNode(
|
NodeRef folder1 = nodeService.createNode(
|
||||||
rootNodeRef,
|
rootNodeRef,
|
||||||
ContentModel.ASSOC_CHILDREN,
|
ContentModel.ASSOC_CHILDREN,
|
||||||
QName.createQName(TEST_NAMESPACE),
|
QName.createQName(TEST_NAMESPACE),
|
||||||
ContentModel.TYPE_FOLDER).getChildRef();
|
ContentModel.TYPE_FOLDER).getChildRef();
|
||||||
|
|
||||||
NodeRef folder2 = nodeService.createNode(
|
NodeRef folder2 = nodeService.createNode(
|
||||||
rootNodeRef,
|
rootNodeRef,
|
||||||
ContentModel.ASSOC_CHILDREN,
|
ContentModel.ASSOC_CHILDREN,
|
||||||
QName.createQName(TEST_NAMESPACE),
|
QName.createQName(TEST_NAMESPACE),
|
||||||
ContentModel.TYPE_FOLDER).getChildRef();
|
ContentModel.TYPE_FOLDER).getChildRef();
|
||||||
|
|
||||||
NodeRef fileToMove = nodeService.createNode(
|
NodeRef fileToMove = nodeService.createNode(
|
||||||
folder1,
|
folder1,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE),
|
QName.createQName(TEST_NAMESPACE),
|
||||||
ContentModel.TYPE_CONTENT).getChildRef();
|
ContentModel.TYPE_CONTENT).getChildRef();
|
||||||
|
|
||||||
nodeService.moveNode(
|
nodeService.moveNode(
|
||||||
fileToMove,
|
fileToMove,
|
||||||
folder2,
|
folder2,
|
||||||
ContentModel.ASSOC_CONTAINS,
|
ContentModel.ASSOC_CONTAINS,
|
||||||
QName.createQName(TEST_NAMESPACE));
|
QName.createQName(TEST_NAMESPACE));
|
||||||
|
|
||||||
assertEquals(folder2, nodeService.getPrimaryParent(fileToMove).getParentRef());
|
assertEquals(folder2, nodeService.getPrimaryParent(fileToMove).getParentRef());
|
||||||
|
|
||||||
@@ -989,8 +1031,7 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
checkNumOfEvents(3);
|
checkNumOfEvents(3);
|
||||||
|
|
||||||
final String folder2ID = getNodeResource(2).getId();
|
final String folder2ID = getNodeResource(2).getId();
|
||||||
final String moveFileParentAfterMove =
|
final String moveFileParentAfterMove = getNodeResource(3).getPrimaryHierarchy().get(0);
|
||||||
getNodeResource(3).getPrimaryHierarchy().get(0);
|
|
||||||
|
|
||||||
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
assertEquals("Wrong node parent.", folder2ID, moveFileParentAfterMove);
|
||||||
}
|
}
|
||||||
@@ -1003,7 +1044,6 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
|
|||||||
final Set<String> originalAspects = resource.getAspectNames();
|
final Set<String> originalAspects = resource.getAspectNames();
|
||||||
assertNotNull(originalAspects);
|
assertNotNull(originalAspects);
|
||||||
|
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(() -> {
|
retryingTransactionHelper.doInTransaction(() -> {
|
||||||
// Add cm:geographic aspect with default value
|
// Add cm:geographic aspect with default value
|
||||||
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
nodeService.addAspect(nodeRef, ContentModel.ASPECT_GEOGRAPHIC, null);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.RenditionModel;
|
import org.alfresco.model.RenditionModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
@@ -776,4 +777,57 @@ public class RenditionService2IntegrationTest extends AbstractRenditionIntegrati
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTextExtractTransformAllowedWhenThumbnailDisabled()
|
||||||
|
{
|
||||||
|
// create a source node
|
||||||
|
NodeRef sourceNodeRef = createSource(ADMIN, "quick.pdf");
|
||||||
|
assertNotNull("Node not generated", sourceNodeRef);
|
||||||
|
String replyQueue = "org.test.queue";
|
||||||
|
String targetMimetype = MimetypeMap.MIMETYPE_TEXT_PLAIN;
|
||||||
|
|
||||||
|
TransformDefinition textExtractTransform = new TransformDefinition(
|
||||||
|
targetMimetype,
|
||||||
|
java.util.Collections.emptyMap(),
|
||||||
|
"clientData",
|
||||||
|
replyQueue,
|
||||||
|
"requestId");
|
||||||
|
|
||||||
|
renditionService2.setThumbnailsEnabled(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Should NOT throw, as this is a text extract transform
|
||||||
|
AuthenticationUtil.runAs(() -> {
|
||||||
|
transactionService.getRetryingTransactionHelper().doInTransaction(() -> {
|
||||||
|
renditionService2.transform(sourceNodeRef, textExtractTransform);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}, ADMIN);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
renditionService2.setThumbnailsEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataExtractTransformAllowedWhenThumbnailDisabled()
|
||||||
|
{
|
||||||
|
// create a source node
|
||||||
|
NodeRef sourceNodeRef = createSource(ADMIN, "quick.pdf");
|
||||||
|
assertNotNull("Node not generated", sourceNodeRef);
|
||||||
|
renditionService2.setThumbnailsEnabled(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Should NOT throw, as this is a metadata extract transform
|
||||||
|
extract(ADMIN, sourceNodeRef);
|
||||||
|
waitForExtract(ADMIN, sourceNodeRef, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
renditionService2.setThumbnailsEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user