Compare commits

...

101 Commits

Author SHA1 Message Date
alfresco-build
eca25addff [maven-release-plugin][skip ci] prepare release 23.7.0.6 2025-11-05 10:17:14 +00:00
Gerard Olenski
0ea417ed37 ACS-10528 Bump jakarta mail to 2.0.2 (#3635) (#3637) 2025-11-05 09:57:43 +01:00
alfresco-build
fb811cdb2d [maven-release-plugin][skip ci] prepare for next development iteration 2025-11-04 12:04:33 +00:00
alfresco-build
9c0ac89015 [maven-release-plugin][skip ci] prepare release 23.7.0.5 2025-11-04 12:04:31 +00:00
Damian Ujma
1028b5c44b ACS-10456 Backport camel and netty version bump to 23.N (#3634) 2025-11-04 11:42:53 +01:00
alfresco-build
39d209a6a1 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-31 11:42:38 +00:00
alfresco-build
d9adbd60e1 [maven-release-plugin][skip ci] prepare release 23.7.0.4 2025-10-31 11:42:36 +00:00
Somnath-Deshmukh
cb07b26653 MNT-25422 Backporting to 23.N (#3628)
Bulleted list, numbered list, and underline are not working properly when adding comment in the file. Backporting to 23.N
2025-10-31 15:50:32 +05:30
SanjoyHyland2025
327129f021 Merge pull request #3618 from Alfresco/fix/MNT-25186_23.N
MNT-25186: fixed the tags and category filters for elasticsearch
2025-10-24 16:46:06 +05:30
alfresco-build
afbaf11ff9 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-22 09:56:07 +00:00
alfresco-build
e779057f23 [maven-release-plugin][skip ci] prepare release 23.7.0.3 2025-10-22 09:56:05 +00:00
Debjit Chattopadhyay
49ee9f8f29 Revert "MNT-24776 adding if-else conditionals to avoid null values"
Revert "MNT-24776 adding if-else conditionals to avoid null values"
2025-10-22 14:33:52 +05:30
Debjit Chattopadhyay
213886cedd Revert "MNT-24776 adding if-else conditionals to avoid null values"
This reverts commit 353d50a35c.
2025-10-22 13:13:42 +05:30
Sanjoy Das
1be9a43bcd MNT-25186: fixed the tags and category filters for elasticsearch 2025-10-22 12:17:37 +05:30
alfresco-build
eceb7c0eb3 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-21 11:39:39 +00:00
alfresco-build
8cd46d4585 [maven-release-plugin][skip ci] prepare release 23.7.0.2 2025-10-21 11:39:37 +00:00
Debjit Chattopadhyay
11d71e1941 (MNT-24776) Category Picker Error when a User does not have Read Permissions to a Category
(MNT-24776) Category Picker Error when a User does not have Read Permissions to a Category
2025-10-21 15:30:44 +05:30
Debjit Chattopadhyay
353d50a35c MNT-24776 adding if-else conditionals to avoid null values
(cherry picked from commit be02be5a8b)
2025-10-21 12:12:06 +05:30
alfresco-build
2daafc711d [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-19 04:45:23 +00:00
alfresco-build
dfa94fbe21 [maven-release-plugin][skip ci] prepare release 23.7.0.1 2025-10-19 04:45:22 +00:00
Somnath-Deshmukh
4a93aec66b MNT-25359 Validating and Sanitizing the comment before posting (#3615)
MNT-25359 Validating and Sanitizing the comment before posting to prevent any XSS attack
2025-10-17 21:00:11 +05:30
Jakub Kochman
3f0bbc9844 Updating release/23.N branch to 23.7.0 after 23.6.0 ACS release [skip ci] 2025-10-10 11:19:17 +02:00
alfresco-build
cb9ad42101 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-09 16:41:21 +00:00
alfresco-build
ca385b3bbc [maven-release-plugin][skip ci] prepare release 23.6.0.33 2025-10-09 16:41:20 +00:00
Kacper Magdziarz
19c1582f1e [ACS-10423] Bump IE/SS to 2.0.17 (#3612) 2025-10-09 17:38:42 +02:00
alfresco-build
06a918b082 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-09 13:44:28 +00:00
alfresco-build
f543de9959 [maven-release-plugin][skip ci] prepare release 23.6.0.32 2025-10-09 13:44:26 +00:00
Debjit Chattopadhyay
8124279e6a Merge pull request #3610 from Alfresco/fix/revert_MNT_24776
Revert "MNT-24776 adding if-else conditionals to avoid null values"
2025-10-09 18:27:59 +05:30
Debjit Chattopadhyay
4281fd5b2d Revert "MNT-24776 adding if-else conditionals to avoid null values"
This reverts commit 393b064918.
2025-10-09 18:14:50 +05:30
alfresco-build
d10d88306b [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-09 10:12:06 +00:00
alfresco-build
1d7a37cd8c [maven-release-plugin][skip ci] prepare release 23.6.0.31 2025-10-09 10:12:04 +00:00
Debjit Chattopadhyay
4bcb795452 Merge pull request #3609 from Alfresco/fix/MNT-24776_backport_to_23.N
MNT-24776 backport to release/23.N
2025-10-09 14:34:25 +05:30
Debjit Chattopadhyay
393b064918 MNT-24776 adding if-else conditionals to avoid null values
(cherry picked from commit be02be5a8b)
2025-10-09 13:29:30 +05:30
alfresco-build
f741f2ca45 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-08 15:59:31 +00:00
alfresco-build
ef676f11e4 [maven-release-plugin][skip ci] prepare release 23.6.0.30 2025-10-08 15:59:29 +00:00
cezary-witkowski
478c81fee3 [ACS-10454] Bump AOS to fix "Edit in Microsoft Office" error (#3606) 2025-10-08 16:57:01 +02:00
alfresco-build
cf9cc8042d [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-06 13:25:18 +00:00
alfresco-build
8d790ed1cb [maven-release-plugin][skip ci] prepare release 23.6.0.29 2025-10-06 13:25:16 +00:00
cezary-witkowski
87c7bd2877 [ACS-10454] Bump AOS to fix "Edit in Microsoft Office" error (#3602) 2025-10-06 14:16:10 +02:00
alfresco-build
9125f889b0 [maven-release-plugin][skip ci] prepare for next development iteration 2025-10-03 11:40:58 +00:00
alfresco-build
2fb74d2691 [maven-release-plugin][skip ci] prepare release 23.6.0.28 2025-10-03 11:40:56 +00:00
Gerard Olenski
d671162dae ACS-10427 Bump ATS 4.2.2 (#3601) 2025-10-03 12:54:03 +02:00
alfresco-build
bfaa629da7 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-26 17:19:48 +00:00
alfresco-build
719d73a558 [maven-release-plugin][skip ci] prepare release 23.6.0.27 2025-09-26 17:19:46 +00:00
Piotr Żurek
a2aa867f3f ACS-9665 Fix formatting 2025-09-26 18:34:04 +02:00
Piotr Żurek
8d745c536a Cherry pick ACS-9665 add event generation extensions (#3593) 280a873cb6 Piotr Żurek <Piotr.Zurek@hyland.com> 26 Sep 2025 at 10:25 2025-09-26 18:25:10 +02:00
alfresco-build
b0f4c21ae3 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-26 12:31:24 +00:00
alfresco-build
72494e34fa [maven-release-plugin][skip ci] prepare release 23.6.0.26 2025-09-26 12:31:22 +00:00
Tiago Salvado
792b7024ea [ACS-9940] Bump spring security version to 6.4.11 (#3592) (#3594) 2025-09-26 12:44:25 +01:00
alfresco-build
40a1371f0d [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-25 20:52:06 +00:00
alfresco-build
c22c47e63f [maven-release-plugin][skip ci] prepare release 23.6.0.25 2025-09-25 20:52:03 +00:00
Tiago Salvado
232299d42d [ACS-10155] Bump spring version to 6.2.11 (#3589) (#3591) 2025-09-25 21:04:30 +01:00
alfresco-build
aca7969849 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-25 10:22:26 +00:00
alfresco-build
4ab2bbd3d6 [maven-release-plugin][skip ci] prepare release 23.6.0.24 2025-09-25 10:22:24 +00:00
Debjit Chattopadhyay
f68f02372d Merge pull request #3590 from Alfresco/fix/MNT-24776_revert
Revert MNT-24776 as this fix is affecting other scenarios.
2025-09-25 15:05:51 +05:30
Debjit Chattopadhyay
9b0eedc8c1 Revert MNT-24776 as this fix is affecting other scenarios. 2025-09-25 13:19:23 +05:30
alfresco-build
f164dedcee [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-23 12:55:06 +00:00
alfresco-build
9cdaa0a265 [maven-release-plugin][skip ci] prepare release 23.6.0.23 2025-09-23 12:55:04 +00:00
cezary-witkowski
ef034e596b [ACS-10041] Repository - CPU spikes and OOM errors with SQL Server 2019 (#3588) 2025-09-23 14:10:29 +02:00
alfresco-build
1251081a69 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-23 11:20:49 +00:00
alfresco-build
2d16eb6f42 [maven-release-plugin][skip ci] prepare release 23.6.0.22 2025-09-23 11:20:47 +00:00
Gerard Olenski
e577134875 ACS-10195 Bump Tika and ATS (#3587) 2025-09-23 12:37:56 +02:00
alfresco-build
510eadd565 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-22 12:43:25 +00:00
alfresco-build
187646895c [maven-release-plugin][skip ci] prepare release 23.6.0.21 2025-09-22 12:43:22 +00:00
Tiago Salvado
f9515e336f [ACS-10166] Include qname and namespace in NodeIdsWhichReferenceContentUrl query (#3579) (#3582) 2025-09-22 12:57:36 +01:00
alfresco-build
828dd20576 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-22 09:21:07 +00:00
alfresco-build
3372e20c35 [maven-release-plugin][skip ci] prepare release 23.6.0.20 2025-09-22 09:21:05 +00:00
Gerard Olenski
64b5cace27 ACS-10159 Bump ATS (#3581) 2025-09-22 10:12:37 +02:00
alfresco-build
83acf26cf4 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-18 11:13:01 +00:00
alfresco-build
b3be0f2b7f [maven-release-plugin][skip ci] prepare release 23.6.0.19 2025-09-18 11:12:59 +00:00
Belal Ansari
7a6ebb9a05 Backporting MNT-25216 Error on fixedAclUpdaterJobDetail execution when using Oracle to ACS 23 (#3575) 2025-09-18 15:57:15 +05:30
alfresco-build
fa0f239618 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-17 01:05:50 +00:00
alfresco-build
43799408a8 [maven-release-plugin][skip ci] prepare release 23.6.0.18 2025-09-17 01:05:48 +00:00
Tiago Salvado
e7305006f0 [ACS-9929] Bump cxf version to 4.1.2 (#3572) 2025-09-17 01:21:54 +01:00
alfresco-build
40c30411af [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-12 11:02:12 +00:00
alfresco-build
91f8b43237 [maven-release-plugin][skip ci] prepare release 23.6.0.17 2025-09-12 11:02:09 +00:00
Eva Vasques
6fccf828e1 ACS-10042 - AGS Concurrent IPR Group Creation (#3566) (#3570) 2025-09-12 11:10:43 +01:00
alfresco-build
3fac3373c9 [maven-release-plugin][skip ci] prepare for next development iteration 2025-09-04 08:24:19 +00:00
alfresco-build
ee857ce1de [maven-release-plugin][skip ci] prepare release 23.6.0.16 2025-09-04 08:24:17 +00:00
Debjit Chattopadhyay
483d7fab21 Merge pull request #3563 from Alfresco/fix/MNT-24776-backport-23.N
backport MNT-24776 to 23.N
2025-09-04 13:01:59 +05:30
Debjit Chattopadhyay
590209b299 Fix for "MNT-24776 : Category Picker Error when a User does not have Read Permissions to a Category"
(cherry picked from commit 626640ddc7)
2025-09-03 15:14:48 +05:30
alfresco-build
376514df67 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-29 13:30:01 +00:00
alfresco-build
7144a2dd94 [maven-release-plugin][skip ci] prepare release 23.6.0.15 2025-08-29 13:29:59 +00:00
Debjit Chattopadhyay
b4da3d8c20 MNT-24308 - fix search filterquery creation for displaying favourites in Share for both Solr and Elasticsearch
MNT-24308 : On click of 'My Favorites' link under 'Documents' in the left panel of 'Document Library' page, all the links appear grayed out
2025-08-29 18:15:59 +05:30
Debjit Chattopadhyay
62de9ff0c0 MNT-24308 : On click of 'My Favorites' link under 'Documents' in the left panel of 'Document Library' page, all the links appear grayed out 2025-08-29 16:25:23 +05:30
alfresco-build
a11acce720 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-28 13:37:40 +00:00
alfresco-build
1128011e15 [maven-release-plugin][skip ci] prepare release 23.6.0.14 2025-08-28 13:37:38 +00:00
Tiago Salvado
d0cb45de0d [MNT-25242] Add property to control if scope is cleaned (#3520) (#3550) 2025-08-28 11:18:05 +01:00
alfresco-build
2b48195896 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-28 10:12:53 +00:00
alfresco-build
fbb95d6a7f [maven-release-plugin][skip ci] prepare release 23.6.0.13 2025-08-28 10:12:51 +00:00
cezary-witkowski
502427e852 [ACS-9933] Use only lang3 3.18 in 23.N (#3547)
Signed-off-by: cezary-witkowski <cezary.witkowski@hyland.com>
2025-08-28 11:31:18 +02:00
alfresco-build
3ff2d79641 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-22 11:54:40 +00:00
alfresco-build
f274b88ece [maven-release-plugin][skip ci] prepare release 23.6.0.12 2025-08-22 11:54:38 +00:00
SatyamSah5
21550ec30b ACS-9991 Allow Content and Metadata extract even if thumbnails are disabled (#3537) 2025-08-22 16:39:46 +05:30
alfresco-build
8665267225 [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-07 20:47:40 +00:00
alfresco-build
984b0bc719 [maven-release-plugin][skip ci] prepare release 23.6.0.11 2025-08-07 20:47:38 +00:00
Eva Vasques
5b89fc0be7 MNT-24975 - Repeated IPR groups due to casing inconsistencies on creation (#3510) 2025-08-07 21:04:26 +01:00
alfresco-build
bf3a3382fd [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-07 13:51:45 +00:00
alfresco-build
14d007fae8 [maven-release-plugin][skip ci] prepare release 23.6.0.10 2025-08-07 13:51:43 +00:00
Eva Vasques
79317ddc9d ACS-9923 Removing an aspect needs to invoke onUpdateProperties (#3504) (#3506) 2025-08-07 13:51:29 +01:00
alfresco-build
c0e762fe5e [maven-release-plugin][skip ci] prepare for next development iteration 2025-08-06 06:04:44 +00:00
60 changed files with 10804 additions and 10142 deletions

View File

@@ -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 }}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -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"

View File

@@ -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>

View File

@@ -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,7 +176,8 @@ 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
* contentUrl content URL
* @return Set<NodeRef> set of nodes that reference the provided content URL * @return Set<NodeRef> set of nodes that reference the provided content URL
*/ */
@Override @Override
@@ -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())
{ {
@@ -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);

View File

@@ -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.
@@ -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,12 +161,10 @@ 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
@@ -236,7 +241,8 @@ 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
* group name
* @return Set<String> immediate authorities * @return Set<String> immediate authorities
*/ */
private Set<String> getAuthorities(String group) private Set<String> getAuthorities(String group)
@@ -296,7 +302,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl
* <p> * <p>
* Return null if none found. * Return null if none found.
* *
* @param nodeRef node reference * @param nodeRef
* node reference
* @return Pair<String, String> where first is the read group and second if the write group, null if none found * @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
* @param authorities
* authorities
* @return String full group name * @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)
@@ -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);
} }
@@ -497,8 +507,10 @@ 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)
@@ -519,8 +531,10 @@ 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
* @param authorities
* authorities
* @return String group prefix short name * @return String group prefix short name
*/ */
/* package */ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities) /* package */ String getIPRGroupPrefixShortName(String prefix, Set<String> authorities)
@@ -539,10 +553,14 @@ 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
* @param writers
* write authorities
* @param index
* group index
* @return String group short name * @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)
@@ -555,10 +573,14 @@ 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
* @param writers
* write authorities
* @param index
* group index
* @return String group short name * @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)
@@ -573,7 +595,8 @@ 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
* set of authorities
* @return int hash code * @return int hash code
*/ */
private int getAuthoritySetHashCode(Set<String> authorities) private int getAuthoritySetHashCode(Set<String> authorities)
@@ -589,9 +612,12 @@ 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
* child authorities
* @param index
* group index
* @return String full name of created group * @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)
@@ -624,8 +650,8 @@ 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);
} }

View File

@@ -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));
@@ -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
@@ -189,8 +195,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
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);
@@ -198,8 +203,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}); });
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);
@@ -208,22 +212,20 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}); });
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)
.getNodeRef();
recordService.createRecord(filePlan, record); recordService.createRecord(filePlan, record);
return 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
@@ -233,8 +235,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}, 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
@@ -244,8 +245,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}, 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
@@ -255,8 +255,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}, 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
@@ -266,8 +265,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}, 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
@@ -277,8 +275,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}, 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
@@ -292,4 +289,238 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase
} }
}); });
} }
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);
}
}
} }

View File

@@ -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=

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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());

View File

@@ -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
* *
@@ -124,6 +133,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
if (totalItemCount === 0) totalItemCount = -1; if (totalItemCount === 0) totalItemCount = -1;

View File

@@ -181,6 +181,8 @@ var Filters =
case "favourites": case "favourites":
for (var favourite in favourites) for (var favourite in favourites)
{
if (favourite && favourite.trim() !== "")
{ {
if (filterQuery) if (filterQuery)
{ {
@@ -188,6 +190,7 @@ var Filters =
} }
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;
@@ -231,7 +240,7 @@ var Filters =
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":
@@ -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")

View File

@@ -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);
} }

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -37,7 +37,6 @@ 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/

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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
View File

@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <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>

View File

@@ -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>

View File

@@ -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.
@@ -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);
@@ -229,8 +256,7 @@ 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;

View File

@@ -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>

View File

@@ -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
@@ -36,8 +36,7 @@ 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
@@ -87,10 +86,8 @@ public class ReferenceablePropertiesEntity
/** /**
* Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties. * Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties.
*/ */
public static void addReferenceableProperties(Node node, Map<QName, Serializable> properties) public static void addReferenceableProperties(Long nodeId, NodeRef nodeRef, Map<QName, Serializable> properties)
{ {
Long nodeId = node.getId();
NodeRef nodeRef = node.getNodeRef();
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol()); properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId()); properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());

View File

@@ -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";

View File

@@ -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();
} }
/** /**

View File

@@ -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;
@@ -208,6 +211,15 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
this.observerInstructionCount = observerInstructionCount; this.observerInstructionCount = observerInstructionCount;
} }
/**
* @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()
*/ */
@@ -614,7 +626,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
} }
finally finally
{ {
if (!secure) if (!secure && cleanScope)
{ {
unsetScope(model, scope); unsetScope(model, scope);
} }

View File

@@ -39,6 +39,10 @@ import java.util.Locale;
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.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.node.ChildAssocEntity; import org.alfresco.repo.domain.node.ChildAssocEntity;
@@ -99,9 +103,6 @@ import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.alfresco.util.PropertyMap; import org.alfresco.util.PropertyMap;
import org.alfresco.util.transaction.TransactionListenerAdapter; import org.alfresco.util.transaction.TransactionListenerAdapter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* Node service using database persistence layer to fulfill functionality * Node service using database persistence layer to fulfill functionality
@@ -150,7 +151,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
/** /**
* *
* @param policyBehaviourFilter component used to enable and disable behaviours * @param policyBehaviourFilter
* component used to enable and disable behaviours
*/ */
public void setPolicyBehaviourFilter(BehaviourFilter policyBehaviourFilter) public void setPolicyBehaviourFilter(BehaviourFilter policyBehaviourFilter)
{ {
@@ -158,11 +160,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Set whether <b>cm:auditable</b> timestamps should be propagated to parent nodes * Set whether <b>cm:auditable</b> timestamps should be propagated to parent nodes where the parent-child relationship has been marked using <b>propagateTimestamps</b>.
* where the parent-child relationship has been marked using <b>propagateTimestamps</b>.
* *
* @param enableTimestampPropagation <tt>true</tt> to propagate timestamps to the parent * @param enableTimestampPropagation
* node where appropriate * <tt>true</tt> to propagate timestamps to the parent node where appropriate
*/ */
public void setEnableTimestampPropagation(boolean enableTimestampPropagation) public void setEnableTimestampPropagation(boolean enableTimestampPropagation)
{ {
@@ -172,9 +173,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
/** /**
* Performs a null-safe get of the node * Performs a null-safe get of the node
* *
* @param nodeRef the node to retrieve * @param nodeRef
* the node to retrieve
* @return Returns the node entity (never null) * @return Returns the node entity (never null)
* @throws InvalidNodeRefException if the referenced node could not be found * @throws InvalidNodeRefException
* if the referenced node could not be found
*/ */
private Pair<Long, NodeRef> getNodePairNotNull(NodeRef nodeRef) throws InvalidNodeRefException private Pair<Long, NodeRef> getNodePairNotNull(NodeRef nodeRef) throws InvalidNodeRefException
{ {
@@ -264,7 +267,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* @throws UnsupportedOperationException Always * @throws UnsupportedOperationException
* Always
*/ */
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class) @Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public void deleteStore(StoreRef storeRef) throws InvalidStoreRefException public void deleteStore(StoreRef storeRef) throws InvalidStoreRefException
@@ -434,23 +438,23 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
return childAssocRef; return childAssocRef;
} }
/** /**
* Adds all the aspects and properties required for the given node, along with mandatory aspects * Adds all the aspects and properties required for the given node, along with mandatory aspects and related properties. Existing values will not be overridden. All required pre- and post-update notifications are sent for missing aspects.
* and related properties.
* Existing values will not be overridden. All required pre- and post-update notifications
* are sent for missing aspects.
* *
* @param nodePair the node to which the details apply * @param nodePair
* @param classQName the type or aspect QName for which the defaults must be applied. * the node to which the details apply
* If this is <tt>null</tt> then properties and aspects are only applied * @param classQName
* for 'extra' aspects and 'extra' properties. * the type or aspect QName for which the defaults must be applied. If this is <tt>null</tt> then properties and aspects are only applied for 'extra' aspects and 'extra' properties.
* @param existingAspects the existing aspects or <tt>null</tt> to have them fetched * @param existingAspects
* @param existingProperties the existing properties or <tt>null</tt> to have them fetched * the existing aspects or <tt>null</tt> to have them fetched
* @param extraAspects any aspects that should be added to the 'missing' set (may be <tt>null</tt>) * @param existingProperties
* @param extraProperties any properties that should be added the the 'missing' set (may be <tt>null</tt>) * the existing properties or <tt>null</tt> to have them fetched
* @param overwriteExistingProperties <tt>true</tt> if the extra properties must completely overwrite * @param extraAspects
* the existing properties * any aspects that should be added to the 'missing' set (may be <tt>null</tt>)
* @param extraProperties
* any properties that should be added the the 'missing' set (may be <tt>null</tt>)
* @param overwriteExistingProperties
* <tt>true</tt> if the extra properties must completely overwrite the existing properties
* @return <tt>true</tt> if properties or aspects were added * @return <tt>true</tt> if properties or aspects were added
*/ */
private boolean addAspectsAndProperties( private boolean addAspectsAndProperties(
@@ -595,11 +599,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Get any aspects that should be added given the type, properties and existing aspects. * Get any aspects that should be added given the type, properties and existing aspects. Note that this <b>does not</b> included a search for properties required for the missing aspects.
* Note that this <b>does not</b> included a search for properties required for the missing
* aspects.
* *
* @param classQName the type, aspect or association * @param classQName
* the type, aspect or association
* @return Returns any aspects that should be added * @return Returns any aspects that should be added
*/ */
private Set<QName> getMissingAspects( private Set<QName> getMissingAspects(
@@ -669,8 +672,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* @param existingProperties existing node properties * @param existingProperties
* @param classQNames the types or aspects to introspect * existing node properties
* @param classQNames
* the types or aspects to introspect
* @return Returns any properties that should be added * @return Returns any properties that should be added
*/ */
private Map<QName, Serializable> getMissingProperties(Map<QName, Serializable> existingProperties, Set<QName> classQNames) private Map<QName, Serializable> getMissingProperties(Map<QName, Serializable> existingProperties, Set<QName> classQNames)
@@ -838,9 +843,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
throw new IllegalArgumentException("The aspect is reserved for system use: " + aspectTypeQName); throw new IllegalArgumentException("The aspect is reserved for system use: " + aspectTypeQName);
} }
/* /* Note: Aspect and property removal is resilient to missing dictionary definitions */
* Note: Aspect and property removal is resilient to missing dictionary definitions
*/
// get the node // get the node
final Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef); final Pair<Long, NodeRef> nodePair = getNodePairNotNull(nodeRef);
final Long nodeId = nodePair.getFirst(); final Long nodeId = nodePair.getFirst();
@@ -859,22 +862,31 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
if (aspectDef != null) if (aspectDef != null)
{ {
// Remove default properties // Remove default properties
Map<QName, Serializable> propsBefore = nodeDAO.getNodeProperties(nodeId);
Map<QName, PropertyDefinition> propertyDefs = aspectDef.getProperties(); Map<QName, PropertyDefinition> propertyDefs = aspectDef.getProperties();
Set<QName> propertyToRemoveQNames = propertyDefs.keySet(); Set<QName> propertyToRemoveQNames = propertyDefs.keySet();
nodeDAO.removeNodeProperties(nodeId, propertyToRemoveQNames); boolean propertiesRemoved = nodeDAO.removeNodeProperties(nodeId, propertyToRemoveQNames);
if (propertiesRemoved)
{
invokeOnUpdateProperties(
nodeRef,
propsBefore, // before
nodeDAO.getNodeProperties(nodeId)); // after
}
// Remove child associations // Remove child associations
// We have to iterate over the associations and remove all those between the parent and child // We have to iterate over the associations and remove all those between the parent and child
final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5); final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5);
final List<Pair<Long, NodeRef>> nodesToDelete = new ArrayList<Pair<Long, NodeRef>>(5); final List<Pair<Long, NodeRef>> nodesToDelete = new ArrayList<Pair<Long, NodeRef>>(5);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return true; return true;
} }
@Override public boolean orderResults() @Override
public boolean orderResults()
{ {
return false; return false;
} }
@@ -907,8 +919,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get all the QNames to remove // Get all the QNames to remove
Set<QName> assocTypeQNamesToRemove = new HashSet<QName>(aspectDef.getChildAssociations().keySet()); Set<QName> assocTypeQNamesToRemove = new HashSet<QName>(aspectDef.getChildAssociations().keySet());
@@ -1037,7 +1048,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* @throws IllegalStateException if the node is pending delete * @throws IllegalStateException
* if the node is pending delete
* *
* @see #KEY_PENDING_DELETE_NODES * @see #KEY_PENDING_DELETE_NODES
*/ */
@@ -1064,9 +1076,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
/** /**
* Delete a node * Delete a node
* *
* @param nodeRef the node to delete * @param nodeRef
* @param allowArchival <tt>true</tt> if normal archival may occur or * the node to delete
* <tt>false</tt> if the node must be forcibly deleted * @param allowArchival
* <tt>true</tt> if normal archival may occur or <tt>false</tt> if the node must be forcibly deleted
*/ */
private void deleteNode(NodeRef nodeRef, boolean allowArchival) private void deleteNode(NodeRef nodeRef, boolean allowArchival)
{ {
@@ -1364,8 +1377,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
// We have to iterate over the associations and remove all those between the parent and child // We have to iterate over the associations and remove all those between the parent and child
final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5); final List<Pair<Long, ChildAssociationRef>> assocsToDelete = new ArrayList<Pair<Long, ChildAssociationRef>>(5);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return true; return true;
@@ -1394,8 +1406,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
nodeDAO.getChildAssocs(parentNodeId, childNodeId, null, null, null, null, callback); nodeDAO.getChildAssocs(parentNodeId, childNodeId, null, null, null, null, callback);
@@ -1584,8 +1595,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Gets the properties map, sets the value (null is allowed) and checks that the new set * Gets the properties map, sets the value (null is allowed) and checks that the new set of properties is valid.
* of properties is valid.
* *
*/ */
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class) @Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
@@ -1625,14 +1635,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Ensures that all required properties are present on the node and copies the * Ensures that all required properties are present on the node and copies the property values to the <code>Node</code>.
* property values to the <code>Node</code>.
* <p> * <p>
* To remove a property, <b>remove it from the map</b> before calling this method. * To remove a property, <b>remove it from the map</b> before calling this method. Null-valued properties are allowed.
* Null-valued properties are allowed.
* <p> * <p>
* If any of the values are null, a marker object is put in to mimic nulls. They will be turned back into * If any of the values are null, a marker object is put in to mimic nulls. They will be turned back into a real nulls when the properties are requested again.
* a real nulls when the properties are requested again.
* *
*/ */
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class) @Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
@@ -1740,8 +1747,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10);
// We have a callback handler to filter results // We have a callback handler to filter results
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return false; return false;
@@ -1771,8 +1777,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get the assocs pointing to it // Get the assocs pointing to it
@@ -1829,8 +1834,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
// We have a callback handler to filter results // We have a callback handler to filter results
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10);
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return preload; return preload;
@@ -1860,8 +1864,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get the assocs pointing to it // Get the assocs pointing to it
QName typeQName = (typeQNamePattern instanceof QName) ? (QName) typeQNamePattern : null; QName typeQName = (typeQNamePattern instanceof QName) ? (QName) typeQNamePattern : null;
@@ -1881,8 +1884,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return true; return true;
@@ -1905,8 +1907,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get all child associations with the specific qualified name // Get all child associations with the specific qualified name
nodeDAO.getChildAssocsByChildTypes(nodeId, childNodeTypeQNames, callback); nodeDAO.getChildAssocsByChildTypes(nodeId, childNodeTypeQNames, callback);
@@ -1945,8 +1946,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return true; return true;
@@ -1969,8 +1969,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get all child associations with the specific qualified name // Get all child associations with the specific qualified name
nodeDAO.getChildAssocs(nodeId, assocTypeQName, childNames, callback); nodeDAO.getChildAssocs(nodeId, assocTypeQName, childNames, callback);
@@ -2103,8 +2102,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(100);
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return false; return false;
@@ -2125,8 +2123,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get the child associations that meet the criteria // Get the child associations that meet the criteria
nodeDAO.getChildAssocsWithoutParentAssocsOfType(parentNodeId, assocTypeQName, callback); nodeDAO.getChildAssocsWithoutParentAssocsOfType(parentNodeId, assocTypeQName, callback);
@@ -2143,6 +2140,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
return nodeDAO.selectAssocsNotLinkedByTwoOtherAssocs(parentNodeId); return nodeDAO.selectAssocsNotLinkedByTwoOtherAssocs(parentNodeId);
} }
/** /**
* Specific properties <b>not</b> supported by {@link #getChildAssocsByPropertyValue(NodeRef, QName, Serializable)} * Specific properties <b>not</b> supported by {@link #getChildAssocsByPropertyValue(NodeRef, QName, Serializable)}
*/ */
@@ -2179,8 +2177,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10); final List<ChildAssociationRef> results = new ArrayList<ChildAssociationRef>(10);
// We have a callback handler to filter results // We have a callback handler to filter results
ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() ChildAssocRefQueryCallback callback = new ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return false; return false;
@@ -2202,8 +2199,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// Get the assocs pointing to it // Get the assocs pointing to it
nodeDAO.getChildAssocsByPropertyValue(nodeId, propertyQName, value, callback); nodeDAO.getChildAssocsByPropertyValue(nodeId, propertyQName, value, callback);
@@ -2308,6 +2304,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
// done // done
return nodeAssocRefs; return nodeAssocRefs;
} }
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class) @Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<AssociationRef> getSourceAssocs(NodeRef targetRef, QNamePattern qnamePattern) public List<AssociationRef> getSourceAssocs(NodeRef targetRef, QNamePattern qnamePattern)
{ {
@@ -2350,8 +2347,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* When searching for <code>primaryOnly == true</code>, checks that there is exactly * When searching for <code>primaryOnly == true</code>, checks that there is exactly one path.
* one path.
*/ */
@Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class) @Extend(traitAPI = NodeServiceTrait.class, extensionAPI = NodeServiceExtension.class)
public List<Path> getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException public List<Path> getPaths(NodeRef nodeRef, boolean primaryOnly) throws InvalidNodeRefException
@@ -2381,8 +2377,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
/** /**
* Archive (direct copy) a node hierarchy * Archive (direct copy) a node hierarchy
* *
* @param walker the node hierarchy to archive * @param walker
* @param archiveStoreRef StoreRef * the node hierarchy to archive
* @param archiveStoreRef
* StoreRef
*/ */
private void archiveHierarchyImpl(NodeHierarchyWalker walker, StoreRef archiveStoreRef) private void archiveHierarchyImpl(NodeHierarchyWalker walker, StoreRef archiveStoreRef)
{ {
@@ -2880,8 +2878,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
{ {
// Get the node's children, but only one's that aren't in the same store // Get the node's children, but only one's that aren't in the same store
final List<ChildAssociationRef> childAssocs = new LinkedList<ChildAssociationRef>(); final List<ChildAssociationRef> childAssocs = new LinkedList<ChildAssociationRef>();
NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() NodeDAO.ChildAssocRefQueryCallback callback = new NodeDAO.ChildAssocRefQueryCallback() {
{
public boolean preLoadNodes() public boolean preLoadNodes()
{ {
return true; return true;
@@ -2896,8 +2893,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
public boolean handle( public boolean handle(
Pair<Long, ChildAssociationRef> childAssocPair, Pair<Long, ChildAssociationRef> childAssocPair,
Pair<Long, NodeRef> parentNodePair, Pair<Long, NodeRef> parentNodePair,
Pair<Long, NodeRef> childNodePair Pair<Long, NodeRef> childNodePair)
)
{ {
// Add it if it's not in the target store // Add it if it's not in the target store
NodeRef childNodeRef = childNodePair.getSecond(); NodeRef childNodeRef = childNodePair.getSecond();
@@ -2911,8 +2907,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
public void done() public void done()
{ {}
}
}; };
// We need to get all primary children and do the store filtering ourselves // We need to get all primary children and do the store filtering ourselves
nodeDAO.getChildAssocs(nodeId, null, null, null, Boolean.TRUE, null, callback); nodeDAO.getChildAssocs(nodeId, null, null, null, Boolean.TRUE, null, callback);
@@ -2957,8 +2952,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Ensures name uniqueness for the child and the child association. Note that nothing is done if the * Ensures name uniqueness for the child and the child association. Note that nothing is done if the association type doesn't enforce name uniqueness.
* association type doesn't enforce name uniqueness.
* *
* @return Returns <tt>true</tt> if the child association <b>cm:name</b> was written * @return Returns <tt>true</tt> if the child association <b>cm:name</b> was written
*/ */
@@ -2983,12 +2977,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* Propagate, if necessary, a <b>cm:modified</b> timestamp change to the parent of the * Propagate, if necessary, a <b>cm:modified</b> timestamp change to the parent of the given association, along with the <b>cm:modifier</b> of who changed it. The parent node has to be <b>cm:auditable</b> and the association has to be marked for propagation as well.
* given association, along with the <b>cm:modifier</b> of who changed it.
* The parent node has to be <b>cm:auditable</b> and the association
* has to be marked for propagation as well.
* *
* @param assocRef the association to propagate along * @param assocRef
* the association to propagate along
*/ */
private void propagateTimeStamps(ChildAssociationRef assocRef) private void propagateTimeStamps(ChildAssociationRef assocRef)
{ {
@@ -3082,9 +3074,9 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
private static final String KEY_AUDITABLE_PROPAGATION_PRE = "node.auditable.propagation.pre"; private static final String KEY_AUDITABLE_PROPAGATION_PRE = "node.auditable.propagation.pre";
private static final String KEY_AUDITABLE_PROPAGATION_POST = "node.auditable.propagation.post"; private static final String KEY_AUDITABLE_PROPAGATION_POST = "node.auditable.propagation.post";
private AuditableTransactionListener auditableTransactionListener = new AuditableTransactionListener(); private AuditableTransactionListener auditableTransactionListener = new AuditableTransactionListener();
/** /**
* Wrapper to set the <b>cm:modified</b> time and <b>cm:modifier</b> on * Wrapper to set the <b>cm:modified</b> time and <b>cm:modifier</b> on individual nodes.
* individual nodes.
* *
* @author Derek Hulley * @author Derek Hulley
* @since 3.4.6 * @since 3.4.6
@@ -3123,9 +3115,12 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
/** /**
* @param parentNodeIds the parent node IDs that need to be touched for <b>cm:modified</b>, and the updating child node from which to get the <b>cm:modifier</b> from * @param parentNodeIds
* @param modifiedDate the date to set * the parent node IDs that need to be touched for <b>cm:modified</b>, and the updating child node from which to get the <b>cm:modifier</b> from
* @param useCurrentTxn <tt>true</tt> to use the current transaction * @param modifiedDate
* the date to set
* @param useCurrentTxn
* <tt>true</tt> to use the current transaction
*/ */
private void process(final Map<Long, Long> parentNodeIds, Date modifiedDate, boolean useCurrentTxn) private void process(final Map<Long, Long> parentNodeIds, Date modifiedDate, boolean useCurrentTxn)
{ {
@@ -3139,17 +3134,20 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
/** /**
* Touch a single node in a new, writable txn * Touch a single node in a new, writable txn
* *
* @param parentNodeId the parent node to touch * @param parentNodeId
* @param childNodeId the child node from which to get the <b>cm:modifier</b> from * the parent node to touch
* @param modifiedDate the date to set * @param childNodeId
* @param useCurrentTxn <tt>true</tt> to use the current transaction * the child node from which to get the <b>cm:modifier</b> from
* @param modifiedDate
* the date to set
* @param useCurrentTxn
* <tt>true</tt> to use the current transaction
*/ */
private void processSingle(final Long parentNodeId, final Long childNodeId, final Date modifiedDate, boolean useCurrentTxn) private void processSingle(final Long parentNodeId, final Long childNodeId, final Date modifiedDate, boolean useCurrentTxn)
{ {
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper(); RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
txnHelper.setMaxRetries(1); txnHelper.setMaxRetries(1);
RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() {
{
@Override @Override
public Void execute() throws Throwable public Void execute() throws Throwable
{ {
@@ -3237,7 +3235,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl implements Extens
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <M extends Trait> ExtendedTrait<M> getTrait(Class<? extends M> traitAPI) public <M extends Trait> ExtendedTrait<M> getTrait(Class<? extends M> traitAPI)

View File

@@ -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
@@ -28,8 +28,10 @@ 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 * Filterable/Sortable Node Entity
@@ -42,12 +44,17 @@ import org.alfresco.repo.domain.node.NodePropertyEntity;
public class FilterSortNodeEntity public class FilterSortNodeEntity
{ {
private Long id; // node id private Long id; // node id
private String nodeUuid;
private Long typeQNameId;
private NodeEntity node; private AuditablePropertiesEntity auditablePropertiesEntity;
private NodePropertyEntity prop1; private NodePropertyEntity prop1;
private NodePropertyEntity prop2; private NodePropertyEntity prop2;
private NodePropertyEntity prop3; private NodePropertyEntity prop3;
private String storeProtocol;
private String storeIdentifier;
// Supplemental query-related parameters // Supplemental query-related parameters
private Long parentNodeId; private Long parentNodeId;
private Long prop1qnameId; private Long prop1qnameId;
@@ -80,6 +87,26 @@ public class FilterSortNodeEntity
this.id = id; this.id = id;
} }
public String getNodeUuid()
{
return nodeUuid;
}
public void setNodeUuid(String nodeUuid)
{
this.nodeUuid = nodeUuid;
}
public Long getTypeQNameId()
{
return typeQNameId;
}
public void setTypeQNameId(Long typeQNameId)
{
this.typeQNameId = typeQNameId;
}
public String getPattern() public String getPattern()
{ {
return pattern; return pattern;
@@ -100,8 +127,7 @@ public class FilterSortNodeEntity
sb.append(escapeChar); sb.append(escapeChar);
offset = idx + 1; offset = idx + 1;
} }
} } while (idx != -1);
while(idx != -1);
sb.append(s.substring(offset)); sb.append(s.substring(offset));
return sb.toString(); return sb.toString();
} }
@@ -137,6 +163,16 @@ public class FilterSortNodeEntity
this.namePropertyQNameId = namePropertyQNameId; this.namePropertyQNameId = namePropertyQNameId;
} }
public AuditablePropertiesEntity getAuditablePropertiesEntity()
{
return auditablePropertiesEntity;
}
public void setAuditablePropertiesEntity(AuditablePropertiesEntity auditablePropertiesEntity)
{
this.auditablePropertiesEntity = auditablePropertiesEntity;
}
public NodePropertyEntity getProp1() public NodePropertyEntity getProp1()
{ {
return prop1; return prop1;
@@ -167,14 +203,24 @@ public class FilterSortNodeEntity
this.prop3 = prop3; this.prop3 = prop3;
} }
public NodeEntity getNode() public String getStoreProtocol()
{ {
return node; return storeProtocol;
} }
public void setNode(NodeEntity childNode) public void setStoreProtocol(String storeProtocol)
{ {
this.node = childNode; this.storeProtocol = storeProtocol;
}
public String getStoreIdentifier()
{
return storeIdentifier;
}
public void setStoreIdentifier(String storeIdentifier)
{
this.storeIdentifier = storeIdentifier;
} }
// Supplemental query-related parameters // Supplemental query-related parameters
@@ -258,4 +304,9 @@ public class FilterSortNodeEntity
{ {
this.isPrimary = isPrimary; this.isPrimary = isPrimary;
} }
public NodeRef createNodeRef()
{
return new NodeRef(new StoreRef(storeProtocol, storeIdentifier), nodeUuid);
}
} }

View File

@@ -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
@@ -38,13 +38,16 @@ 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.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.query.CannedQueryParameters; import org.alfresco.query.CannedQueryParameters;
import org.alfresco.query.CannedQuerySortDetails; import org.alfresco.query.CannedQuerySortDetails;
import org.alfresco.query.CannedQuerySortDetails.SortOrder; import org.alfresco.query.CannedQuerySortDetails.SortOrder;
import org.alfresco.repo.domain.node.AuditablePropertiesEntity; import org.alfresco.repo.domain.node.AuditablePropertiesEntity;
import org.alfresco.repo.domain.node.Node;
import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.node.NodeEntity; import org.alfresco.repo.domain.node.NodeEntity;
import org.alfresco.repo.domain.node.NodePropertyEntity; import org.alfresco.repo.domain.node.NodePropertyEntity;
@@ -69,15 +72,11 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.AlfrescoCollator; import org.alfresco.util.AlfrescoCollator;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/** /**
* GetChildren canned query * GetChildren canned query
* *
* To get paged list of children of a parent node filtered by child type. * To get paged list of children of a parent node filtered by child type. Also optionally filtered and/or sorted by one or more properties (up to three).
* Also optionally filtered and/or sorted by one or more properties (up to three).
* *
* @author janv * @author janv
* @since 4.0 * @since 4.0
@@ -100,7 +99,6 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
public static final QName FILTER_QNAME_NODE_IS_PRIMARY = QName.createQName("", "IS_PRIMARY"); public static final QName FILTER_QNAME_NODE_IS_PRIMARY = QName.createQName("", "IS_PRIMARY");
private NodeDAO nodeDAO; private NodeDAO nodeDAO;
private QNameDAO qnameDAO; private QNameDAO qnameDAO;
private CannedQueryDAO cannedQueryDAO; private CannedQueryDAO cannedQueryDAO;
@@ -246,7 +244,6 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
filterSortPropCnt = setFilterSortParams(sortFilterProps, params); filterSortPropCnt = setFilterSortParams(sortFilterProps, params);
List<NodeRef> result = new ArrayList<>(0); List<NodeRef> result = new ArrayList<>(0);
try try
@@ -777,7 +774,8 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (results.size() >= BATCH_SIZE) if (results.size() >= BATCH_SIZE)
{ {
// batch // batch
preloadFilterSort(); preloadNodes();
filterSort();
} }
results.add(result); results.add(result);
@@ -790,24 +788,27 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
if (results.size() >= 0) if (results.size() >= 0)
{ {
// finish batch // finish batch
preloadFilterSort(); preloadNodes();
filterSort();
} }
} }
private void preloadFilterSort() private void preloadNodes()
{ {
List<NodeRef> nodeRefs = new ArrayList<>(results.size()); List<NodeRef> nodeRefs = new ArrayList<>(results.size());
for (FilterSortNodeEntity result : results) for (FilterSortNodeEntity result : results)
{ {
nodeRefs.add(result.getNode().getNodeRef()); nodeRefs.add(result.createNodeRef());
} }
preload(nodeRefs); preload(nodeRefs);
}
private void filterSort()
{
for (FilterSortNodeEntity result : results) for (FilterSortNodeEntity result : results)
{ {
Node node = result.getNode(); NodeRef nodeRef = result.createNodeRef();
NodeRef nodeRef = node.getNodeRef();
Map<NodePropertyKey, NodePropertyValue> propertyValues = new HashMap<NodePropertyKey, NodePropertyValue>(3); Map<NodePropertyKey, NodePropertyValue> propertyValues = new HashMap<NodePropertyKey, NodePropertyValue>(3);
@@ -832,7 +833,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
Map<QName, Serializable> propVals = nodePropertyHelper.convertToPublicProperties(propertyValues); Map<QName, Serializable> propVals = nodePropertyHelper.convertToPublicProperties(propertyValues);
// Add referenceable / spoofed properties (including spoofed name if null) // Add referenceable / spoofed properties (including spoofed name if null)
ReferenceablePropertiesEntity.addReferenceableProperties(node, propVals); ReferenceablePropertiesEntity.addReferenceableProperties(result.getId(), nodeRef, propVals);
// special cases // special cases
@@ -854,7 +855,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
} }
// Auditable props (eg. cm:creator, cm:created, cm:modifier, cm:modified, ...) // Auditable props (eg. cm:creator, cm:created, cm:modifier, cm:modified, ...)
AuditablePropertiesEntity auditableProps = node.getAuditableProperties(); AuditablePropertiesEntity auditableProps = result.getAuditablePropertiesEntity();
if (auditableProps != null) if (auditableProps != null)
{ {
for (Map.Entry<QName, Serializable> entry : auditableProps.getAuditableProperties().entrySet()) for (Map.Entry<QName, Serializable> entry : auditableProps.getAuditableProperties().entrySet())
@@ -864,7 +865,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR
} }
// Node type // Node type
Long nodeTypeQNameId = node.getTypeQNameId(); Long nodeTypeQNameId = result.getTypeQNameId();
if (nodeTypeQNameId != null) if (nodeTypeQNameId != null)
{ {
Pair<Long, QName> pair = qnameDAO.getQName(nodeTypeQNameId); Pair<Long, QName> pair = qnameDAO.getQName(nodeTypeQNameId);

View File

@@ -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);
}
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -133,6 +133,14 @@
<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"/>
@@ -170,7 +178,8 @@
<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,
@@ -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) -->

View File

@@ -30,4 +30,23 @@
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]> <![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
</select> </select>
<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> </mapper>

View File

@@ -30,4 +30,23 @@
<![CDATA[and commit_time_ms <= #{maxCommitTime}]]> <![CDATA[and commit_time_ms <= #{maxCommitTime}]]>
</select> </select>
<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> </mapper>

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -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);
@@ -544,6 +551,49 @@ 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()
{ {
@@ -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());
@@ -845,10 +894,8 @@ 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);
@@ -877,18 +924,15 @@ public class UpdateRepoEventIT extends AbstractContextAwareRepoEvent
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);
} }
@@ -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);
} }
@@ -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);
} }
@@ -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);

View File

@@ -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);
}
}
} }