diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 755fd3a8d1..21a2e0aef1 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -158,3 +158,9 @@ updates:
- "8.16"
registries:
- maven-repository-artifacts-alfresco-com-nexus-content-groups-int
+- package-ecosystem: "docker"
+ directory: "packaging/docker-alfresco/"
+ schedule:
+ interval: "daily"
+ time: "22:00"
+ timezone: Africa/Abidjan
diff --git a/.travis.yml b/.travis.yml
index 9e508c8e48..71ba0fa028 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
---
dist: focal
language: java
-jdk: openjdk11
+jdk: openjdk17
services:
- docker
@@ -53,7 +53,7 @@ jobs:
- name: "Source Clear Scan (SCA)"
stage: test
- if: branch = master OR branch =~ /release\/.*/
+ if: (branch = master OR branch =~ /release\/.*/) AND type != pull_request
# Run Veracode
install: skip
script: travis_wait 30 bash scripts/travis/source_clear.sh
@@ -69,8 +69,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContext01TestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -78,16 +78,16 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContext02TestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext03TestSuite"
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContext03TestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -95,8 +95,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContext04TestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -104,8 +104,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- mkdir -p "${HOME}/tmp"
- cp repository/src/test/resources/realms/alfresco-realm.json "${HOME}/tmp"
- export HOST_IP=$(hostname -I | cut -f1 -d' ')
@@ -116,8 +116,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContext06TestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -125,8 +125,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AppContextExtraTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -134,8 +134,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=MiscContextTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -143,8 +143,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=SearchTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dindex.subsystem.name=solr6
- name: "Repository - MariaDB 10.2.18 tests"
@@ -152,7 +152,7 @@ jobs:
install: skip
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.2.18 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver
- name: "Repository - MariaDB 10.4 tests"
@@ -160,7 +160,7 @@ jobs:
install: skip
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.4 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver
- name: "Repository - MariaDB 10.5 tests"
@@ -168,7 +168,7 @@ jobs:
install: skip
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.5 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver
- name: "Repository - MariaDB 10.6 tests"
@@ -177,7 +177,7 @@ jobs:
install: skip
before_script:
- docker run -d -p 3307:3306 --name mariadb -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mariadb:10.6 --transaction-isolation=READ-COMMITTED --max-connections=300 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.name=alfresco -Ddb.url=jdbc:mariadb://localhost:3307/alfresco?useUnicode=yes\&characterEncoding=UTF-8 -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.driver=org.mariadb.jdbc.Driver
- name: "Repository - MySQL 8 tests"
@@ -186,88 +186,47 @@ jobs:
install: skip
before_script:
- docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=alfresco -e MYSQL_USER=alfresco -e MYSQL_DATABASE=alfresco -e MYSQL_PASSWORD=alfresco mysql:8 --transaction-isolation='READ-COMMITTED'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=com.mysql.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- - name: "Repository - PostgreSQL 10.9 tests"
+ - name: "Repository - PostgreSQL 13.7 tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:10.9 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.7 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- - name: "Repository - PostgreSQL 11.7 tests"
- if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
- install: skip
- before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
-
- - name: "Repository - PostgreSQL 11.12 tests"
- if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
- install: skip
- before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.12 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
-
- - name: "Repository - PostgreSQL 12.4 tests"
- if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
- install: skip
- before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:12.4 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
-
- - name: "Repository - PostgreSQL 12.7 tests"
- if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
- install: skip
- before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:12.7 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
-
- - name: "Repository - PostgreSQL 13.1 tests"
+ - name: "Repository - PostgreSQL 14.4 tests"
# We only run DB tests on the latest version of PostgreSQL on feature branches
- if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip db\]/ AND type != pull_request) OR commit_message =~ /\[db\]/
+ if: commit_message !~ /\[skip db\]/ OR commit_message =~ /\[db\]/ OR commit_message =~ /\[latest db\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.1 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
- script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
-
- - name: "Repository - PostgreSQL 13.3 tests"
- # We only run DB tests on the latest version of PostgreSQL on feature branches
- if: commit_message !~ /\[skip db\]/ OR commit_message =~ /\[latest db\]/
- install: skip
- before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - Messaging tests"
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl repository -am -Dtest=CamelRoutesTest,CamelComponentsTest -DfailIfNoTests=false
- name: "Remote-api - AppContext01TestSuite"
if: commit_message !~ /\[skip repo\]/
install: travis_retry travis_wait 40 env REQUIRES_INSTALLED_ARTIFACTS=true bash scripts/travis/build.sh
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext01TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContext02TestSuite"
if: commit_message !~ /\[skip repo\]/
install: travis_retry travis_wait 40 env REQUIRES_INSTALLED_ARTIFACTS=true bash scripts/travis/build.sh
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext02TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -275,8 +234,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: travis_retry travis_wait 40 env REQUIRES_INSTALLED_ARTIFACTS=true bash scripts/travis/build.sh
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -284,8 +243,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: travis_retry travis_wait 40 env REQUIRES_INSTALLED_ARTIFACTS=true bash scripts/travis/build.sh
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:${TRANSFORMERS_TAG}
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
@@ -293,8 +252,8 @@ jobs:
if: commit_message !~ /\[skip repo\]/
install: travis_retry travis_wait 40 env REQUIRES_INSTALLED_ARTIFACTS=true bash scripts/travis/build.sh
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
- - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.16.1
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
+ - docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.17.1-jre11-rockylinux8
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContextExtraTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "REST API TAS tests part1"
@@ -305,6 +264,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part1 -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
- name: "REST API TAS tests part2"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -313,6 +273,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part2 -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
- name: "REST API TAS tests part3"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -321,6 +282,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 60 mvn -B verify -f packaging/tests/tas-restapi/pom.xml -Pall-tas-tests,run-restapi-part3 -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-restapi"
- name: "CMIS TAS tests - BROWSER binding"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -329,6 +291,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-browser -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
- name: "CMIS TAS tests - ATOM binding"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -337,6 +300,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-atom -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
- name: "CMIS TAS tests - WEBSERVICES binding"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -345,6 +309,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal+transforms.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 40 mvn -B verify -f packaging/tests/tas-cmis/pom.xml -Pall-tas-tests,run-cmis-webservices -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-cmis"
- name: "Email TAS tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -353,6 +318,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-email/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-email"
- name: "WebDAV TAS tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -361,6 +327,7 @@ jobs:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-webdav/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-webdav"
- name: "Integration TAS tests"
if: (branch =~ /(release\/.*$|master)/ AND commit_message !~ /\[skip tas\]/) OR commit_message =~ /\[tas\]/
@@ -368,13 +335,15 @@ jobs:
before_script:
- ${TAS_SCRIPTS}/start-compose.sh ${TAS_ENVIRONMENT}/docker-compose-minimal.yml
- ${TAS_SCRIPTS}/wait-for-alfresco-start.sh "http://localhost:8082/alfresco"
+ - travis_retry travis_wait 40 mvn install -pl :alfresco-community-repo-integration-test -am -DskipTests -Pall-tas-tests
script: travis_wait 30 mvn -B verify -f packaging/tests/tas-integration/pom.xml -Pall-tas-tests -Denvironment=default -DrunBugs=false
+ after_failure: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/tas-integration"
- name: "Share Services - ShareServicesTestSuite"
if: commit_message !~ /\[skip repo\]/
install: skip
before_script:
- - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:13.3 postgres -c 'max_connections=300'
+ - docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:14.4 postgres -c 'max_connections=300'
script: travis_wait 20 mvn -B test -pl :alfresco-share-services -am -Dtest=ShareServicesTestSuite -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "AGS Unit & Integration Tests 01 (PostgreSQL)"
diff --git a/amps/ags/pom.xml b/amps/ags/pom.xml
index 0f444eef6d..a5b6714d7b 100644
--- a/amps/ags/pom.xml
+++ b/amps/ags/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-community-repo-amps
- 17.43-SNAPSHOT
+ 20.5-SNAPSHOT
@@ -30,16 +30,20 @@
maven-surefire-plugin
+
--illegal-access=permit
+ --add-opens=java.base/java.lang=ALL-UNNAMED
maven-failsafe-plugin
+
--illegal-access=permit
+ --add-opens=java.base/java.lang=ALL-UNNAMED
diff --git a/amps/ags/rm-automation/pom.xml b/amps/ags/rm-automation/pom.xml
index 4bdf70134f..8e6a0f17ab 100644
--- a/amps/ags/rm-automation/pom.xml
+++ b/amps/ags/rm-automation/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-governance-services-community-parent
- 17.43-SNAPSHOT
+ 20.5-SNAPSHOT
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
index 09128c4e92..12bdc84810 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-governance-services-automation-community-repo
- 17.43-SNAPSHOT
+ 20.5-SNAPSHOT
@@ -45,7 +45,7 @@
org.slf4jslf4j-reload4j
- 1.7.35
+ ${dependency.slf4j.version}test
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/LinksAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/LinksAPI.java
new file mode 100644
index 0000000000..0eb10ff546
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/LinksAPI.java
@@ -0,0 +1,73 @@
+/*-
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.v0;
+
+import org.alfresco.rest.core.v0.BaseAPI;
+import org.apache.http.HttpResponse;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.springframework.stereotype.Component;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.text.MessageFormat;
+import java.util.List;
+
+/**
+ * Methods to make API requests using v0 API for Linking Records
+ *
+ * @author Kavit Shah
+ * @since 3.2
+ */
+@Component
+public class LinksAPI extends BaseAPI {
+
+ private static final String LINK_API = "{0}doclib/action/rm-link/site/rm/documentLibrary/{1}";
+
+ /**
+ * Creates the Link
+ *
+ * @param user The username of the user to use.
+ * @param password The password of the user.
+ * @param expectedStatusCode The expected return status code.
+ * @param sourcePath The Source of link the record. This should be in the format
+ * "{site}/{container}/{path}", "{site}/{container}", "{store_type}/{store_id}/{id}/{path}",
+ * "{store_type}/{store_id}/{id}" or "{store_type}/{store_id}".
+ * @param nodeRefs The Node that needs to be linked.
+ * @return The HTTP Response.
+ * @throws AssertionError If the API didn't return the expected status code.
+ */
+ public HttpResponse linkRecord(String user, String password, int expectedStatusCode, String sourcePath, List nodeRefs) throws UnsupportedEncodingException {
+ JSONObject requestParams = new JSONObject();
+ requestParams.put("nodeRefs", new JSONArray(nodeRefs));
+
+ return doSlingshotPostJsonRequest(user, password, expectedStatusCode, requestParams,
+ MessageFormat.format(LINK_API, "{0}", sourcePath));
+ }
+
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RMAuditAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RMAuditAPI.java
index f63a6efb50..6844a829e0 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RMAuditAPI.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RMAuditAPI.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.rest.v0;
+import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
@@ -36,6 +37,7 @@ import java.util.List;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.util.PojoUtility;
+import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -58,6 +60,8 @@ public class RMAuditAPI extends BaseAPI
private static final String RM_AUDIT_API = "{0}rma/admin/rmauditlog";
private static final String RM_AUDIT_LOG_API = RM_AUDIT_API + "?{1}";
+ private static final String RM_AUDIT_LOG_AS_RECORD = "{0}node/{1}/rmauditlog";
+
/**
* Returns a list of rm audit entries .
*
@@ -84,6 +88,21 @@ public class RMAuditAPI extends BaseAPI
return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
}
+ /**
+ * Returns a list of rm audit entries .
+ *
+ * @param user The username of the user to use.
+ * @param password The password of the user.
+ * @param size Maximum number of log entries to return
+ * @return return All return log entries
+ */
+ public List getRMAuditLogAll(String user, String password, final int size) {
+ String parameters = "size=" + size;
+ JSONArray auditEntries = doGetRequest(user, password,
+ MessageFormat.format(RM_AUDIT_LOG_API,"{0}", parameters)).getJSONObject("data").getJSONArray("entries");
+ return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
+ }
+
/**
* Clear the list of audit entries.
*
@@ -100,5 +119,19 @@ public class RMAuditAPI extends BaseAPI
&& getRMAuditLog(username, password, 100, null).size() == 2);
}
+ /**
+ * Logs the Audit Log as Record.
+ *
+ * @param username The username of the user to use.
+ * @param password The password of the user.
+ * @param recNodeRef The Record Node reference for which Audit log should be created as record
+ * @param destinationNodeRef The Folder id Node reference where the html file should be placed
+ * @throws AssertionError If the API call didn't create the Audit Log as Record.
+ */
+ public HttpResponse logsAuditLogAsRecord(String username, String password, String recNodeRef, String destinationNodeRef) {
+ JSONObject requestParams = new JSONObject();
+ requestParams.put("destination", destinationNodeRef);
+ return doPostJsonRequest(username, password, SC_OK, requestParams, RM_AUDIT_LOG_AS_RECORD,recNodeRef);
+ }
}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordCategoriesAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordCategoriesAPI.java
index 0233e99781..17fee78f10 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordCategoriesAPI.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordCategoriesAPI.java
@@ -52,7 +52,7 @@ public class RecordCategoriesAPI extends BaseAPI
private static final String RM_ACTIONS_API = "{0}rma/actions/ExecutionQueue";
private static final String DISPOSITION_ACTIONS_API = "{0}node/{1}/dispositionschedule/dispositionactiondefinitions";
private static final String DISPOSITION_SCHEDULE_API = "{0}node/{1}/dispositionschedule";
-
+ private static final String NEXT_DISPOSITION_ACTIONS_API = "{0}node/{1}/nextdispositionaction";
/**
* Creates a retention schedule for the category given as parameter
@@ -191,4 +191,19 @@ public class RecordCategoriesAPI extends BaseAPI
retentionProperties.put(RETENTION_SCHEDULE.RETENTION_INSTRUCTIONS, instructions);
return retentionProperties;
}
+
+ /**
+ * Get the Next Disposition Action
+ *
+ * @param user
+ * @param password
+ * @param recordId
+ * @return the next disposition schedule action
+ */
+ public JSONObject getNextDispositionAction(String user, String password, String recordId)
+ {
+ String nodeRef = NODE_PREFIX + recordId;
+ JSONObject nextDispositionAction = doGetRequest(user, password, MessageFormat.format(NEXT_DISPOSITION_ACTIONS_API, "{0}", nodeRef));
+ return nextDispositionAction;
+ }
}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordFoldersAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordFoldersAPI.java
index 04b321664b..25f49971b5 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordFoldersAPI.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordFoldersAPI.java
@@ -74,4 +74,39 @@ public class RecordFoldersAPI extends BaseAPI
return null;
}
+ public HttpResponse postFolderAction(String user, String password, JSONObject requestParams, String recordFolder) {
+ String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
+ try {
+ requestParams.put("nodeRef", recNodeRef);
+ return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
+ }
+ catch (Exception error) {
+ LOGGER.error("Unable to extract response parameter", error);
+ }
+ return null;
+ }
+
+ public HttpResponse postRecordAction(String user, String password, JSONObject requestParams, String recordId) {
+ try {
+ requestParams.put("nodeRef", recordId);
+ return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
+ }
+ catch (JSONException error) {
+ LOGGER.error("Unable to extract response parameter", error);
+ }
+ return null;
+ }
+
+
+ public HttpResponse reOpenRecordFolder(String user, String password, String recordFolder)
+ {
+ String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
+
+ JSONObject requestParams = new JSONObject();
+ requestParams.put("name", "openRecordFolder");
+ requestParams.put("nodeRef", recNodeRef);
+
+ return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
+ }
+
}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordsAPI.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordsAPI.java
index 037476d52f..f06dfabc61 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordsAPI.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/v0/RecordsAPI.java
@@ -360,4 +360,25 @@ public class RecordsAPI extends BaseAPI
{
return getNodeRefSpacesStore() + getItemNodeRef(username, password, recordPath + "/" + recordName);
}
+
+ /**
+ * Reopens the record given as parameter
+ *
+ * @param user the user declaring the document as record
+ * @param password the user's password
+ * @param recordName the record name
+ * @return The HTTP Response.
+ */
+
+ public HttpResponse reOpenRecord(String user, String password, String recordName)
+ {
+ String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordName);
+
+ JSONObject requestParams = new JSONObject();
+ requestParams.put("name", "undeclareRecord");
+ requestParams.put("nodeRef", recNodeRef);
+
+ return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
+ }
+
}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditHoldsTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditHoldsTest.java
new file mode 100644
index 0000000000..dd1e7c4ad2
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/AuditHoldsTest.java
@@ -0,0 +1,146 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.audit;
+import static java.util.Arrays.asList;
+import static org.alfresco.rest.rm.community.base.TestData.*;
+import static org.alfresco.rest.rm.community.model.audit.AuditEvents.ADD_TO_HOLD;
+import static org.alfresco.rest.rm.community.model.audit.AuditEvents.REMOVE_FROM_HOLD;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.core.IsNot.not;
+import static org.springframework.http.HttpStatus.CREATED;
+import static org.testng.AssertJUnit.*;
+
+import java.util.Collections;
+import java.util.List;
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.audit.AuditEvents;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
+import org.alfresco.rest.rm.community.model.user.UserRoles;
+import org.alfresco.rest.v0.HoldsAPI;
+import org.alfresco.rest.v0.service.RMAuditService;
+import org.alfresco.rest.v0.service.RoleService;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.SiteModel;
+import org.alfresco.utility.model.UserModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+public class AuditHoldsTest extends BaseRMRestTest {
+ private final String PREFIX = generateTestPrefix(AuditAddToHoldTests.class);
+ private final String HOLD1 = PREFIX + "hold1";
+ private SiteModel publicSite;
+ private FileModel testFile;
+ @Autowired
+ private RMAuditService rmAuditService;
+ @Autowired
+ private HoldsAPI holdsAPI;
+ @Autowired
+ private RoleService roleService;
+ private UserModel rmAdmin;
+ private RecordCategory recordCategory;
+ private RecordCategoryChild recordFolder1,recordFolder2;
+ private List auditEntries;
+ private String hold1NodeRef;
+ public static final String RECORD_FOLDER_THREE = "record-folder-three";
+ @BeforeClass(alwaysRun = true)
+ public void preconditionForAuditAddToHoldTests()
+ {
+ createRMSiteIfNotExists();
+ rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
+
+ STEP("Create a hold");
+ hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1, HOLD_REASON,
+ HOLD_DESCRIPTION);
+
+ STEP("Create a collaboration site with a test file.");
+ publicSite = dataSite.usingAdmin().createPublicRandomSite();
+ testFile = dataContent.usingAdmin().usingSite(publicSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ STEP("Create a record category with 2 folders and 1 record");
+ recordCategory = createRootCategory(getRandomName("recordCategory"));
+ recordFolder1 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder1");
+ recordFolder2 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder2");
+ Record recordToBeAdded = createElectronicRecord(recordFolder1.getId(), PREFIX + "record");
+ assertStatusCode(CREATED);
+
+ STEP("Add some items to the hold, then remove them from the hold");
+ final List itemsList = asList(testFile.getNodeRefWithoutVersion(), recordToBeAdded.getId(), recordFolder2.getId());
+ final List holdsList = Collections.singletonList(HOLD1);
+ holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), recordToBeAdded.getId(), HOLD1);
+ holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(), itemsList, holdsList);
+
+ STEP("Delete the record folder that was held");
+ getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(recordFolder2.getId());
+
+ STEP("Rename the parent of the record that was held");
+ RecordFolder recordFolder = RecordFolder.builder().name(RECORD_FOLDER_THREE).build();
+ getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(recordFolder, recordFolder1.getId());
+ }
+ /**
+ * Data provider with hold events that have links to held items
+ *
+ * @return the hold events
+ */
+ @DataProvider (name = "holdsEvents")
+ public Object[][] getHoldEvents()
+ {
+ return new AuditEvents[][]
+ {
+ { ADD_TO_HOLD },
+ { REMOVE_FROM_HOLD }
+ };
+ }
+ @Test (dataProvider = "holdsEvents")
+ public void checkItemPathLink(AuditEvents event) {
+ auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), event);
+ assertFalse("Audit results should not be empty",auditEntries.size()==0);
+ final String auditedEvent = event + " - " + testFile.getName();
+ assertTrue("Audit results should contain one " + auditedEvent + " event",auditEntries.stream().anyMatch(e -> e.getEvent().startsWith(event.eventDisplayName)));
+ STEP("Check the audit log contains only an entry for add to hold.");
+ assertThat(auditEntries, is(not(empty())));
+ }
+ @AfterClass(alwaysRun = true)
+ private void cleanup() {
+ dataSite.usingAdmin().deleteSite(publicSite);
+ deleteRecordFolder(recordFolder1.getId());
+ deleteRecordFolder(recordFolder2.getId());
+ deleteRecordCategory(recordCategory.getId());
+ rmAuditService.clearAuditLog();
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/ElectronicRecordAuditLogTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/ElectronicRecordAuditLogTest.java
new file mode 100644
index 0000000000..a868c188c8
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/ElectronicRecordAuditLogTest.java
@@ -0,0 +1,244 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.audit;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMAuditAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.alfresco.utility.model.UserModel;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+public class ElectronicRecordAuditLogTest extends BaseRMRestTest {
+
+ private Optional rmAdmin;
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RMAuditAPI auditLog;
+ @Autowired
+ private RecordsAPI recordApi;
+ /* electronic record details */
+ private static final String AUDIT_ELECTRONIC_RECORD = generateTestPrefix(ElectronicRecordAuditLogTest.class) + "electronic record";
+ private static final String AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD = "Complete Reopen Electronic Record";
+ public static final String TITLE = "Title";
+ public static final String DESCRIPTION = "Description";
+ private RecordCategory category1;
+ private RecordCategoryChild recordFolder1;
+ private Record electronicRecord, electronicRecord2;
+
+ @BeforeClass(alwaysRun = true)
+ public void electronicRecordsAuditLogSetup()
+ {
+ createRMSiteIfNotExists();
+ rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
+ rmRolesAndActionsAPI.assignRoleToUser(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ rmAdmin.get().getUsername(),
+ "Administrator");
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ category1 = createRootCategory(TITLE, DESCRIPTION);
+ recordFolder1 = createFolder(category1.getId(),TITLE);
+
+ electronicRecord = createElectronicRecord(recordFolder1.getId(),AUDIT_ELECTRONIC_RECORD,rmAdmin.get());
+ }
+
+ @Test(description = "Audit log for newly filed electronic record")
+ @AlfrescoTest(jira="RM-4303")
+ public void newElectronicRecordAudit() {
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+
+ // newly created record contains 2 events: "file to" and metadata update
+ // the order in which object creation and metadata update are listed isn't always identical due to
+ // both happening in the same transaction
+ assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
+ assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "newElectronicRecordAudit",
+ description = "Viewing electronic record audit log is itself an auditable event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void electronicRecordAuditIsEvent()
+ {
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "electronicRecordAuditIsEvent",
+ description = "Rename electronic record is an edit metadata event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void renameElectronicRecord() {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ Record renameElectronicRecord = createRecordModel("edited " + electronicRecord.getName(), "", "");
+
+ // rename record
+ getRestAPIFactory().getRecordsAPI().updateRecord(renameElectronicRecord, electronicRecord.getId());
+ assertStatusCode(OK);
+
+ // we expect 1 new event: "metadata update"
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+ }
+
+ @Test (
+ dependsOnMethods = "newElectronicRecordAudit",
+ description = "Complete and reopen electronic record")
+ @AlfrescoTest(jira="RM-4303")
+ public void completeAndReopenElectronicRecord() {
+ electronicRecord2 = createElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD);
+
+ // complete record
+ recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ electronicRecord2.getName());
+
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+ org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
+ List aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
+ // a record must be completed
+ assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
+
+ // Reopen record
+ recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ electronicRecord2.getName());
+
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+ org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
+ List aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
+ // a record mustn't be completed
+ assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "completeAndReopenElectronicRecord",
+ description = "File electronic record's audit log as record"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void fileElectronicRecordAuditLogAsRecord()
+ {
+ // audit log is stored in the same folder, refresh it so that it appears in the list
+ HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ getRecordNodeRef(electronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
+ JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
+ Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
+ .replace("workspace://SpacesStore/",""));
+ // check audit log
+ AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
+ AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
+ }
+
+ private String getFolderNodeRef(String folderId) {
+ return "workspace://SpacesStore/" + folderId;
+ }
+
+ private String getRecordNodeRef(String recordId) {
+ return "workspace/SpacesStore/" + recordId;
+ }
+
+ private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
+ HttpEntity entity = httpResponse.getEntity();
+ String responseString = null;
+ try {
+ responseString = EntityUtils.toString(entity, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ JSONObject result = new JSONObject(responseString);
+ return result;
+ }
+
+ @AfterMethod
+ private void closeAuditLog() {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ }
+
+ @AfterClass(alwaysRun = true)
+ private void electronicRecordAuditLogCleanup() {
+ deleteRecord(electronicRecord.getId());
+ deleteRecordFolder(recordFolder1.getId());
+ deleteRecordCategory(category1.getId());
+ dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
+ }
+}
\ No newline at end of file
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/NonElectronicRecordAuditLogTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/NonElectronicRecordAuditLogTest.java
new file mode 100644
index 0000000000..8b5d6d0c2d
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/NonElectronicRecordAuditLogTest.java
@@ -0,0 +1,246 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.audit;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMAuditAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.alfresco.utility.model.UserModel;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+
+public class NonElectronicRecordAuditLogTest extends BaseRMRestTest {
+ private Optional rmAdmin;
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RMAuditAPI auditLog;
+ @Autowired
+ private RecordsAPI recordApi;
+ private RecordCategory category1;
+ private RecordCategoryChild recordFolder1;
+ private Record nonElectronicRecord , nonElectronicRecord2;
+ private static final String AUDIT_NON_ELECTRONIC_RECORD = generateTestPrefix(NonElectronicRecordAuditLogTest.class) + "non electronic record";
+ private static final String AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD = "Complete Reopen Non-Electronic Record";
+ public static final String TITLE = "Title";
+ public static final String DESCRIPTION = "Description";
+
+ @BeforeClass(alwaysRun = true)
+ public void nonElectronicRecordAuditLogSetup()
+ {
+ createRMSiteIfNotExists();
+ rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
+ rmRolesAndActionsAPI.assignRoleToUser(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ rmAdmin.get().getUsername(),
+ "Administrator");
+
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ category1 = createRootCategory(TITLE, DESCRIPTION);
+ recordFolder1 = createFolder(category1.getId(),TITLE);
+ nonElectronicRecord = createNonElectronicRecord(recordFolder1.getId(),AUDIT_NON_ELECTRONIC_RECORD,rmAdmin.get());
+
+ }
+
+ @Test(description = "Audit log for newly filed non-electronic record")
+ @AlfrescoTest(jira="RM-4303")
+ public void newNonElectronicRecordAudit()
+ {
+
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+
+ // newly created record contains 3 events: "created object", "file to" and metadata update
+ assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
+ assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+ assertTrue("Created Object Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "newNonElectronicRecordAudit",
+ description = "Viewing Non electronic record audit log is itself an auditable event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void nonElectronicRecordAuditIsEvent()
+ {
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
+
+ }
+
+ @Test
+ (
+ dependsOnMethods = "nonElectronicRecordAuditIsEvent",
+ description = "Rename electronic record is an edit metadata event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void renameNonElectronicRecord()
+ {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ Record renameNonElectronicRecord = createRecordModel("edited " + nonElectronicRecord.getName(), "", "");
+
+ // rename record
+ getRestAPIFactory().getRecordsAPI().updateRecord(renameNonElectronicRecord, nonElectronicRecord.getId());
+ assertStatusCode(OK);
+
+ // we expect 1 new event: "metadata update"
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+
+ }
+
+ @Test (dependsOnMethods = "newNonElectronicRecordAudit",description = "Complete and reopen electronic record")
+ @AlfrescoTest(jira="RM-4303")
+ public void completeAndReopenNonElectronicRecord()
+ {
+ nonElectronicRecord2 = createNonElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD);
+
+ // complete record
+ recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ nonElectronicRecord2.getName());
+
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+ org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
+ List aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
+ // a record must be completed
+ assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ List auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
+
+ // Reopen record
+ recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ nonElectronicRecord2.getName());
+
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+ org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
+ List aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
+ // a record mustn't be completed
+ assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
+ assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
+
+ }
+ @Test
+ (
+ dependsOnMethods = "completeAndReopenNonElectronicRecord",
+ description = "File electronic record's audit log as record"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void fileNonElectronicRecordAuditLogAsRecord()
+ {
+ // audit log is stored in the same folder, refresh it so that it appears in the list
+ HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
+ getRecordNodeRef(nonElectronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
+ JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
+ Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
+ .replace("workspace://SpacesStore/",""));
+ // check audit log
+ AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
+ AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
+
+ }
+
+ private String getFolderNodeRef(String folderId) {
+ return "workspace://SpacesStore/" + folderId;
+ }
+
+ private String getRecordNodeRef(String recordId) {
+ return "workspace/SpacesStore/" + recordId;
+ }
+
+ private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
+ HttpEntity entity = httpResponse.getEntity();
+ String responseString = null;
+ try {
+ responseString = EntityUtils.toString(entity, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ JSONObject result = new JSONObject(responseString);
+ return result;
+ }
+ @AfterMethod
+ private void closeAuditLog() {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ }
+
+ @AfterClass(alwaysRun = true)
+ private void nonElectronicRecordAuditLogCleanup() {
+ deleteRecord(nonElectronicRecord.getId());
+ deleteRecord(nonElectronicRecord2.getId());
+ deleteRecordFolder(recordFolder1.getId());
+ deleteRecordCategory(category1.getId());
+ dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordCategoryAuditLogTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordCategoryAuditLogTest.java
new file mode 100644
index 0000000000..f2ec8562d0
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordCategoryAuditLogTest.java
@@ -0,0 +1,120 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.audit;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.v0.RMAuditAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.model.UserModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.List;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+
+public class RecordCategoryAuditLogTest extends BaseRMRestTest {
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RMAuditAPI auditLog;
+
+ private final String TEST_PREFIX = generateTestPrefix(RecordCategoryAuditLogTest.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private static final String AUDIT_CATEGORY = generateTestPrefix(RecordCategoryAuditLogTest.class) + "category";
+ private RecordCategory recordCategoryAudit;
+
+ @BeforeClass(alwaysRun = true)
+ public void recordCategoryAuditLogSetup() {
+ STEP("Create RM Site");
+ createRMSiteIfNotExists();
+
+ STEP("Create RM Admin user");
+ rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
+ getAdminUser().getPassword(),
+ "Administrator");
+ }
+
+ @Test
+ @AlfrescoTest(jira = "RM-2768")
+ public void recordCategoryAudit() throws Exception {
+ STEP("Create root level category");
+ recordCategoryAudit = createRootCategory(AUDIT_CATEGORY);
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ // newly created record category contains 3 events: object creation, inherited permissions set to false and metadata update
+ // the order in which object creation and metadata update are listed isn't always identical due to
+ // both happening in the same transaction
+ assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
+ assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "recordCategoryAudit",
+ description = "Viewing audit log is itself an auditable event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void recordCategoryAuditIsEvent() {
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
+ }
+
+ @Test
+ (
+ dependsOnMethods = "recordCategoryAuditIsEvent",
+ description = "Record category rename is an edit metadata event"
+ )
+ @AlfrescoTest(jira="RM-4303")
+ public void renameRecordCategory() {
+ String categoryName = "Category name " + getRandomAlphanumeric();
+ RecordCategory rootRecordCategory = createRootCategory(categoryName);
+ String newCategoryName = "Rename " + categoryName;
+ RecordCategory recordCategoryUpdated = RecordCategory.builder().name(newCategoryName).build();
+ RecordCategory renamedRecordCategory = getRestAPIFactory().getRecordCategoryAPI().updateRecordCategory(recordCategoryUpdated, rootRecordCategory.getId());
+
+ assertStatusCode(OK);
+ // we expect 1 new event: "metadata update"
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+ }
+ @AfterClass(alwaysRun = true)
+ private void electronicRecordAuditLogCleanup() {
+ deleteRecordCategory(recordCategoryAudit.getId());
+ dataUser.deleteUser(new UserModel(RM_ADMIN,
+ getAdminUser().getPassword()));
+ auditLog.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
+ }
+}
+
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordFolderAuditLogTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordFolderAuditLogTest.java
new file mode 100644
index 0000000000..f8bf2e2686
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/audit/RecordFolderAuditLogTest.java
@@ -0,0 +1,175 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.audit;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
+import org.alfresco.rest.v0.RMAuditAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.alfresco.utility.model.UserModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import java.util.List;
+import java.util.Optional;
+
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
+import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordFolderModel;
+import static org.springframework.http.HttpStatus.OK;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+public class RecordFolderAuditLogTest extends BaseRMRestTest {
+
+ private Optional rmAdmin;
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RMAuditAPI auditLog;
+
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ private RecordCategory category1;
+ private RecordCategoryChild recordFolder1;
+ public static final String TITLE = "Title";
+ public static final String DESCRIPTION = "Description";
+
+ @BeforeClass(alwaysRun = true)
+ public void recordFolderAuditLogSetup() {
+ createRMSiteIfNotExists();
+ rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
+ rmRolesAndActionsAPI.assignRoleToUser(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ rmAdmin.get().getUsername(),
+ "Administrator");
+ }
+
+ @Test(description = "Audit log for empty record folder")
+ @AlfrescoTest(jira = "RM-4303")
+ public void recordFolderAudit() {
+ category1 = createRootCategory(TITLE, DESCRIPTION);
+ recordFolder1 = createFolder(category1.getId(), TITLE);
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
+ assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+
+ }
+
+ @Test
+ (
+ dependsOnMethods = "recordFolderAudit",
+ description = "Viewing record folder audit log is itself an auditable event"
+ )
+ @AlfrescoTest(jira = "RM-4303")
+ public void recordFolderAuditIsEvent() {
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
+
+ }
+
+ @Test
+ (
+ dependsOnMethods = "recordFolderAuditIsEvent",
+ description = "Record folder rename is an edit metadata event"
+ )
+ @AlfrescoTest(jira = "RM-4303")
+ public void renameRecordFolder() {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(), rmAdmin.get().getPassword());
+ RecordFolder renameRecordFolder = createRecordFolderModel(category1.getId(), "edited");
+ getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(renameRecordFolder, recordFolder1.getId());
+ assertStatusCode(OK);
+ // we expect 1 new event: "metadata update"
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+// assertTrue("Move To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Move to")));
+ assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
+
+ }
+
+ @Test(dependsOnMethods = "recordFolderAudit",
+ description = "Close and reopen folder")
+ @AlfrescoTest(jira = "RM-4303")
+ public void closeReopenFolder() {
+ //close folder
+ recordFoldersAPI.closeRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
+ recordFolder1.getName());
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Folder Close Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Close Record Folder")));
+
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ //reopen folder
+ recordFoldersAPI.reOpenRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
+ recordFolder1.getName());
+ try
+ {
+ Utility.sleep(1000, 30000, () ->
+ {
+
+ List auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
+ assertTrue("Reopen Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Open Record Folder")));
+
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+ }
+ @AfterMethod
+ private void closeAuditLog()
+ {
+ auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
+ }
+
+ @AfterClass (alwaysRun = true)
+ public void recordFolderAuditLogCleanup()
+ {
+ deleteRecordFolder(recordFolder1.getId());
+ deleteRecordCategory(category1.getId());
+ dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
+ }
+
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java
index 8830ad3fc7..560a39b4c8 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRMRestTest.java
@@ -53,9 +53,12 @@ import static org.springframework.http.HttpStatus.OK;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
+import java.util.Date;
+import java.util.TimeZone;
import java.util.stream.Collectors;
import lombok.Getter;
@@ -91,6 +94,7 @@ import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.UserModel;
+import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
@@ -121,6 +125,8 @@ public class BaseRMRestTest extends RestTest
@Getter(value = PROTECTED)
private SearchAPI searchApi;
+ protected static final String iso8601_DateFormat="yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
/**
* Asserts the given status code
*
@@ -161,7 +167,7 @@ public class BaseRMRestTest extends RestTest
*/
@Override
@BeforeClass (alwaysRun = true)
- public void checkServerHealth() throws Exception
+ public void checkServerHealth()
{
// Create RM Site if not exist
createRMSiteIfNotExists();
@@ -628,8 +634,8 @@ public class BaseRMRestTest extends RestTest
* Returns search results for the given search term
*
* @param user
- * @param term
- * @param query language
+ * @param q
+ * @param queryLanguage language
* @return
* @throws Exception
*/
@@ -956,5 +962,34 @@ public class BaseRMRestTest extends RestTest
return false;
}
}
+ /**
+ * Helper method to get the Previous Date in the YYYY-MM-ddTHH:mm:ss.SSSXXX format
+ * @param previousDays number of previous days while calculating the date as output
+ * @return previousDate as String in the ISO 8601 Date Format
+ */
+ protected String getIso8601Date(int previousDays) {
+ Date date = new Date(System.currentTimeMillis());
+ Date previousDate = new Date(date.getTime() - previousDays);
+ // Conversion
+ SimpleDateFormat sdf= new SimpleDateFormat(iso8601_DateFormat);;
+ sdf.setTimeZone(TimeZone.getDefault());
+ return sdf.format(previousDate);
+ }
+ /**
+ * Helper method to provide the Edited Disposition Date Json
+ * The Edited Disposition Date is modified to previous date so that CUTOFF & DESTROY Steps will be enabled
+ * @return JsonObject with the format {"name":"editDispositionActionAsOfDate","params":{"asOfDate":{"iso8601":"Previous Date"}}}
+ */
+ protected JSONObject editDispositionDateJson() {
+ JSONObject requestParams = new JSONObject();
+ requestParams.put("name","editDispositionActionAsOfDate");
+ JSONObject params = new JSONObject();
+ requestParams.put("params",params);
+
+ JSONObject asOfDate = new JSONObject();
+ params.put("asOfDate",asOfDate);
+ asOfDate.put("iso8601",getIso8601Date(1));
+ return requestParams;
+ }
}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java
index 22e2c5ed8d..239150aeab 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/DeclareAndFileDocumentAsRecordTests.java
@@ -72,6 +72,7 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
+import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import org.alfresco.utility.model.TestGroup;
@@ -259,6 +260,7 @@ public class DeclareAndFileDocumentAsRecordTests extends BaseRMRestTest
* And the document is not declared as a record
*/
@Test (dataProvider = "invalidDestinationPaths",groups = { TestGroup.NOT_SUPPORTED_ON_SINGLE_PIPELINE })
+ @Ignore
public void declareAndFileToInvalidLocationUsingActionsAPI(String containerPath, String expectedException) throws Exception
{
STEP("Declare document as record with an invalid location parameter value");
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/FileVersionAsRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/FileVersionAsRecordTests.java
index b17d6de141..f3c89606d4 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/FileVersionAsRecordTests.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/files/FileVersionAsRecordTests.java
@@ -61,6 +61,7 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
+import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import org.alfresco.utility.model.TestGroup;
@@ -209,6 +210,7 @@ public class FileVersionAsRecordTests extends BaseRMRestTest
* And the document is not declared as a version record
*/
@Test (dataProvider = "invalidDestinationPaths", groups = { TestGroup.NOT_SUPPORTED_ON_SINGLE_PIPELINE })
+ @Ignore
public void declareVersionAndFileToInvalidLocationUsingActionsAPI(String containerPath, String expectedException) throws Exception
{
STEP("Declare document as record version with an invalid location parameter value");
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordsTestLevel2.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordsTestLevel2.java
new file mode 100644
index 0000000000..c871abd17c
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeclareInPlaceRecordsTestLevel2.java
@@ -0,0 +1,311 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.records;
+
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
+import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainer;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildCollection;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.RulesAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.constants.UserRole;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.FolderModel;
+import org.alfresco.utility.model.SiteModel;
+import org.alfresco.utility.model.UserModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static java.util.Arrays.asList;
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
+import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
+import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
+import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
+import static org.alfresco.rest.rm.community.requests.gscore.api.FilesAPI.PARENT_ID_PARAM;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.http.HttpStatus.CREATED;
+
+public class DeclareInPlaceRecordsTestLevel2 extends BaseRMRestTest {
+ private final String TEST_PREFIX = generateTestPrefix(DeclareInPlaceRecordsTestLevel2.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private final String RECORDS_CATEGORY_ONE = TEST_PREFIX + "category";
+ public static final String RECORD_FOLDER_ONE = "record-folder-one";
+ public static final String RECORD_CATEGORY_TWO = "record-category-two" + System.currentTimeMillis();
+ public static final String RECORD_FOLDER_TWO = "record-folder-two";
+ private final String RULE_NAME = TEST_PREFIX + "rule unfiled";
+ private String unfiledRecordsNodeRef;
+ private RecordCategory RecordCategoryOne, RecordCategoryTwo;
+ private RecordCategoryChild recordFolder;
+ private UnfiledContainer unfiledContainer;
+ private FolderModel testFolder;
+ private SiteModel testSite;
+ private SiteModel privateSite;
+ private UserModel testUser;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private RulesAPI rulesAPI;
+ /**
+ * data prep services
+ */
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+
+ @BeforeClass(alwaysRun = true)
+ public void preConditions() {
+ STEP("Create RM Site");
+ createRMSiteIfNotExists();
+ privateSite = dataSite.usingAdmin().createPrivateRandomSite();
+ }
+
+ /**
+ * Given that a user is the owner of a document
+ * And that user has been deleted
+ * When admin tries to declare the document as a record
+ * Then the document becomes an inplace record
+ */
+ @Test
+ @AlfrescoTest(jira="RM-2584")
+ public void DeclareRecordOwnerDeleted() throws Exception {
+
+ createTestPrecondition();
+
+ // Upload document in a folder in a collaboration site
+ FileModel uploadedDoc = dataContent.usingSite(testSite)
+ .usingUser(testUser)
+ .usingResource(testFolder)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ // delete the test user
+ dataUser.deleteUser(testUser);
+
+ // declare uploadedDocument as record
+ getRestAPIFactory().getFilesAPI(getDataUser().getAdminUser()).declareAsRecord(uploadedDoc.getNodeRefWithoutVersion());
+ assertStatusCode(CREATED);
+
+ // assert that the document is now a record
+ assertTrue(hasRecordAspect(uploadedDoc));
+ }
+ /**
+ * Given that a user is the owner of a document
+ * And that user declare the document as a record
+ * When admin files the record to a category that has a disposition schedule applied on records and a cut off step
+ * And admin completes the record so the pending record action is now Cut off
+ * Then user is still able to see the in place record in original share site location
+ */
+ @Test
+ @AlfrescoTest(jira="MNT-18558")
+ public void inPlaceRecordVisibilityAfterFilingToCategoryWithCutOffStep() throws Exception {
+
+ // create test precondition
+ createTestPrecondition(RECORDS_CATEGORY_ONE);
+
+ //create a disposition schedule on Records level with a cut off step
+ dispositionScheduleService.createCategoryRetentionSchedule(RECORDS_CATEGORY_ONE, true);
+ dispositionScheduleService.addCutOffAfterPeriodStep(RECORDS_CATEGORY_ONE, "day|2", CREATED_DATE);
+
+ //create a folder in category
+ recordFolder = createFolder(getAdminUser(),RecordCategoryOne.getId(),RECORD_FOLDER_ONE);
+
+ // create a File to record folder rule applied on Unfiled Records container
+ fileToRuleAppliedOnUnfiledRecords();
+
+ //create a new test user
+ UserModel testUser = createSiteManager();
+
+ // upload a new document as the user and declare the document as record
+ FileModel uploadedDoc = dataContent.usingSite(privateSite)
+ .usingUser(testUser)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ Record uploadedRecord = getRestAPIFactory().getFilesAPI(getDataUser().getAdminUser()).declareAsRecord(uploadedDoc.getNodeRefWithoutVersion());
+ assertStatusCode(CREATED);
+
+ //Complete the record as admin to be sure that pending action is now Cut off
+ recordsAPI.completeRecord(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), uploadedRecord.getName());
+
+ // As test user navigate to collaboration site documents library and check that the record is still visible
+ dataContent.usingAdmin().usingSite(privateSite).assertContentExist();
+ }
+ /**
+ * Create a user called test
+ * Create a collaboration site
+ * Add the user to the collaboration site as consumer
+ * Create an RM site
+ * In RM, create a new categories under file plan with a cut off step set after an event happens
+ * Under the previously created category create a folder
+ * Set READ-ONLY permission for test user for the folder previously created (the user does not have Read
+ * permissions to the category containing the folder)
+ * In the collaboration site create two files
+ * File as record the first file
+ * Log in with test user and check if he can still see the two files in the collaboration site
+ */
+ @Test
+ @AlfrescoTest (jira = "MNT-22138")
+ public void filesVisibilityAfterFilingToCategoryWithCutOffAfterEventStep() throws Exception {
+
+ //create a category
+ RecordCategoryTwo = createRootCategory(RECORD_CATEGORY_TWO);
+
+ //create a disposition schedule on Records level with a cut off step
+ dispositionScheduleService.createCategoryRetentionSchedule(RECORD_CATEGORY_TWO, true);
+ dispositionScheduleService.addCutOffAfterPeriodStep(RECORD_CATEGORY_TWO, "day|2", CREATED_DATE);
+
+ //create a folder in category
+ recordFolder = createFolder(getAdminUser(),RecordCategoryTwo.getId(),RECORD_FOLDER_TWO);
+
+ //create a new test user
+ UserModel siteConsumer = getDataUser().createRandomTestUser();
+ getDataUser().addUserToSite(siteConsumer,privateSite,UserRole.SiteConsumer);
+
+ // give read permissions to test user
+ getRestAPIFactory().getRMUserAPI().addUserPermission(recordFolder.getId(), siteConsumer, PERMISSION_READ_RECORDS);
+
+ // create two documents
+ FileModel testFile = dataContent.usingSite(new SiteModel(privateSite.getTitle()))
+ .usingAdmin()
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ FileModel testFileNotFiled = dataContent.usingSite(new SiteModel(privateSite.getTitle()))
+ .usingAdmin()
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ // file one of the documents as record
+ getRestAPIFactory().getFilesAPI()
+ .usingParams(String.format("%s=%s", PARENT_ID_PARAM, recordFolder.getId()))
+ .declareAsRecord(testFile.getNodeRefWithoutVersion());
+ getRestAPIFactory().getRmRestWrapper().assertStatusCodeIs(CREATED);
+
+ // As test user navigate to collaboration site documents library and check that both of the documents are
+ // visible
+ STEP("Verify the document in collaboration site is now a record");
+ Assert.assertTrue(hasRecordAspect(testFile), "File should have record aspect");
+ Assert.assertFalse(hasRecordAspect(testFileNotFiled), "File should not have record aspect");
+ }
+
+ private void createTestPrecondition(String categoryName) {
+
+ // create "rm admin" user if it does not exist and assign it to RM Administrator role
+ rmRolesAndActionsAPI.createUserAndAssignToRole(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
+
+ // create category
+ STEP("Create category");
+ RecordCategoryOne = createRootCategory(categoryName,"Title");
+
+ unfiledContainer = getRestAPIFactory().getUnfiledContainersAPI().getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS);
+
+ unfiledRecordsNodeRef = NODE_PREFIX + unfiledContainer.getId();
+ }
+ private void createTestPrecondition() {
+ STEP("Create collab_user user");
+ testUser = getDataUser().createRandomTestUser();
+ testSite = dataSite.usingAdmin().createPublicRandomSite();
+
+ // invite collab_user to Collaboration site with Contributor role
+ getDataUser().addUserToSite(testUser, testSite, UserRole.SiteContributor);
+
+ testFolder = dataContent.usingSite(testSite).usingUser(testUser).createFolder();
+ }
+ private void fileToRuleAppliedOnUnfiledRecords() {
+ unfiledRecordsRuleTeardown();
+
+ // create a rule
+ RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title(RULE_NAME)
+ .description(RULE_NAME)
+ .createRecordPath(false)
+ .path("/" + RECORDS_CATEGORY_ONE + "/" + RECORD_FOLDER_ONE)
+ .runInBackground(true)
+ .actions(asList(ActionsOnRule.FILE_TO.getActionValue()));
+
+ // create a rule on unfiledRecords
+ rulesAPI.createRule(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), unfiledRecordsNodeRef, ruleDefinition);
+ }
+ private void unfiledRecordsRuleTeardown() {
+ rulesAPI.deleteAllRulesOnContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), unfiledRecordsNodeRef);
+ }
+ public UserModel createSiteManager() {
+ UserModel siteManager = getDataUser().createRandomTestUser();
+ getDataUser().addUserToSite(siteManager, privateSite, UserRole.SiteManager);
+ return siteManager;
+ }
+ @AfterClass
+ public void cleanupCategory() {
+ unfiledRecordsRuleTeardown();
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RECORD_FOLDER_ONE);
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RecordCategoryOne.getName());
+ deleteRecordCategory(RecordCategoryOne.getId());
+
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RECORD_FOLDER_TWO);
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, RecordCategoryTwo.getName());
+ deleteRecordCategory(RecordCategoryTwo.getId());
+
+ dataSite.usingAdmin().deleteSite(privateSite);
+ dataSite.usingAdmin().deleteSite(testSite);
+
+ UnfiledContainerChildCollection unfiledContainerChildCollection = getRestAPIFactory()
+ .getUnfiledContainersAPI().getUnfiledContainerChildren(unfiledContainer.getId());
+
+ unfiledContainerChildCollection.getEntries().forEach(unfiledChild ->
+ {
+ if (unfiledChild.getEntry().getIsRecord())
+ {
+ getRestAPIFactory().getRecordsAPI().deleteRecord(unfiledChild.getEntry().getId());
+ }
+ else
+ {
+ getRestAPIFactory().getUnfiledRecordFoldersAPI().deleteUnfiledRecordFolder(unfiledChild.getEntry().getId());
+ }
+ });
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeleteRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeleteRecordTests.java
index 8a6a500e30..79fba332fb 100644
--- a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeleteRecordTests.java
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/DeleteRecordTests.java
@@ -75,6 +75,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
+import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
/**
@@ -102,7 +103,7 @@ public class DeleteRecordTests extends BaseRMRestTest
testSite = dataSite.usingAdmin().createPublicRandomSite();
recordFolder = createCategoryFolderInFilePlan();
unfiledRecordFolder = createUnfiledContainerChild(UNFILED_RECORDS_CONTAINER_ALIAS, getRandomName("Unfiled Folder "),
- UNFILED_RECORD_FOLDER_TYPE);
+ UNFILED_RECORD_FOLDER_TYPE);
}
/** Data provider with electronic and non-electronic records to be deleted */
@@ -133,10 +134,10 @@ public class DeleteRecordTests extends BaseRMRestTest
*
*/
@Test
- (
- dataProvider = "recordsToBeDeleted",
- description = "Admin user can delete records"
- )
+ (
+ dataProvider = "recordsToBeDeleted",
+ description = "Admin user can delete records"
+ )
@AlfrescoTest(jira="RM-4363")
public void adminCanDeleteRecords(String recordId)
{
@@ -154,17 +155,17 @@ public class DeleteRecordTests extends BaseRMRestTest
*
*/
@Test
- (
- description = "User without write permissions can't delete a record"
- )
+ (
+ description = "User without write permissions can't delete a record"
+ )
@AlfrescoTest(jira="RM-4363")
public void userWithoutWritePermissionsCantDeleteRecord()
{
// Create a non-electronic record in unfiled records
UnfiledContainerChild nonElectronicRecord = UnfiledContainerChild.builder()
- .name("Record " + RandomData.getRandomAlphanumeric())
- .nodeType(NON_ELECTRONIC_RECORD_TYPE)
- .build();
+ .name("Record " + RandomData.getRandomAlphanumeric())
+ .nodeType(NON_ELECTRONIC_RECORD_TYPE)
+ .build();
UnfiledContainerChild newRecord = getRestAPIFactory().getUnfiledContainersAPI().createUnfiledContainerChild(nonElectronicRecord, UNFILED_RECORDS_CONTAINER_ALIAS);
assertStatusCode(CREATED);
@@ -187,9 +188,9 @@ public class DeleteRecordTests extends BaseRMRestTest
*
*/
@Test
- (
- description = "User without delete records capability can't delete a record"
- )
+ (
+ description = "User without delete records capability can't delete a record"
+ )
@AlfrescoTest(jira="RM-4363")
public void userWithoutDeleteRecordsCapabilityCantDeleteRecord()
{
@@ -234,7 +235,7 @@ public class DeleteRecordTests extends BaseRMRestTest
STEP("Create a record in first folder and copy it into second folder.");
String recordId = getRestAPIFactory().getRecordFolderAPI()
- .createRecord(createElectronicRecordModel(), recordFolder.getId(), getFile(IMAGE_FILE)).getId();
+ .createRecord(createElectronicRecordModel(), recordFolder.getId(), getFile(IMAGE_FILE)).getId();
String copyId = copyNode(recordId, recordFolderB.getId()).getId();
assertStatusCode(CREATED);
@@ -318,14 +319,14 @@ public class DeleteRecordTests extends BaseRMRestTest
RecordCategoryChild recFolder = createFolder(recordCategory.getId(), getRandomName("recFolder"));
RecordBodyFile recordBodyFile = RecordBodyFile.builder().targetParentId(recFolder.getId()).build();
Record recordFiled = getRestAPIFactory().getRecordsAPI().fileRecord(recordBodyFile, testFile.getNodeRefWithoutVersion());
- getRestAPIFactory().getRecordsAPI().completeRecord(recordFiled.getId());
- assertStatusCode(CREATED);
+ completeRecord(recordFiled.getId());
+ assertStatusCode(OK);
STEP("Execute the disposition schedule steps.");
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getUsername(), recordFiled.getName(),
- RM_ACTIONS.CUT_OFF);
+ RM_ACTIONS.CUT_OFF);
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getUsername(), recordFiled.getName(),
- RM_ACTIONS.DESTROY);
+ RM_ACTIONS.DESTROY);
STEP("Check that it's possible to load the copy content.");
getNodeContent(copy.getId());
@@ -348,14 +349,14 @@ public class DeleteRecordTests extends BaseRMRestTest
STEP("Declare file version as record.");
recordsAPI.declareDocumentVersionAsRecord(getAdminUser().getUsername(), getAdminUser().getPassword(), testSite.getId(),
- testFile.getName());
+ testFile.getName());
UnfiledContainerChild unfiledContainerChild = getRestAPIFactory().getUnfiledContainersAPI()
- .getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
- .getEntries().stream()
- .filter(child -> child.getEntry().getName()
- .startsWith(testFile.getName().substring(0, testFile.getName().indexOf("."))))
- .findFirst()
- .get().getEntry();
+ .getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
+ .getEntries().stream()
+ .filter(child -> child.getEntry().getName()
+ .startsWith(testFile.getName().substring(0, testFile.getName().indexOf("."))))
+ .findFirst()
+ .get().getEntry();
STEP("Delete the record.");
deleteAndVerify(unfiledContainerChild.getId());
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/ShareRecordsTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/ShareRecordsTest.java
new file mode 100644
index 0000000000..12495f12b4
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/records/ShareRecordsTest.java
@@ -0,0 +1,128 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.records;
+
+import org.alfresco.dataprep.ContentService;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.apache.commons.httpclient.HttpStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+
+/**
+ * Tests to cover share action for records
+ * @author Kavit Shah
+ */
+public class ShareRecordsTest extends BaseRMRestTest {
+
+ /** data prep services*/
+ @Autowired
+ private RecordsAPI service;
+ @Autowired
+ private ContentService contentService;
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ /** Constants*/
+ private final String TEST_PREFIX = generateTestPrefix(ShareRecordsTest.class);
+ private final String CATEGORY = "CategoryWithSharedRecords" + TEST_PREFIX;
+ private final String FOLDER = "FolderWithSharedRecords" + TEST_PREFIX;
+ private final String ELECTRONIC_RECORD = "ELECTRONIC_RECORD" + TEST_PREFIX;
+ private final String NONELECTRONIC_REC = "NON_ELECTRONIC_RECORD" + TEST_PREFIX;
+ private RecordCategory category;
+ private RecordCategoryChild recordCategoryChild;
+ /**
+ * Given a record
+ * When admin tries to share it via API
+ * Then the record can't be shared
+ */
+ @Test
+ @AlfrescoTest(jira = "RM-5308")
+ public void shareRecordViaApi()
+ {
+ //create RM Site
+ createRMSiteIfNotExists();
+
+ //create a category
+ category = createRootCategory(CATEGORY);
+
+ //create folder
+ recordCategoryChild = createFolder(category.getId(),FOLDER);
+
+ createNonElectronicRecord(recordCategoryChild.getId(),NONELECTRONIC_REC);
+
+ // create record to be shared
+ createElectronicRecord(recordCategoryChild.getId(),ELECTRONIC_RECORD);
+
+ //get the node id for the ELECTRONIC_RECORD created
+ String nodeRefRec1= contentService.getNodeRefByPath(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ "/Sites/" + RM_SITE_ID + "/documentLibrary/" + CATEGORY + "/" + FOLDER + "/" + service.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, ELECTRONIC_RECORD));
+ //check record can't be shared
+ assertFalse("The record has been succesfully shared",
+ service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),nodeRefRec1 ).getKey());
+ //check the error code when trying to share a record
+ assertEquals("The API response code is not " + HttpStatus.SC_INTERNAL_SERVER_ERROR, service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec1).getValue(),
+ String.valueOf( HttpStatus.SC_INTERNAL_SERVER_ERROR));
+
+ //get the node id for NONELECTRONIC_REC created
+ String nodeRefRec2 = contentService.getNodeRefByPath(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ "/Sites/" + RM_SITE_ID + "/documentLibrary/" + CATEGORY + "/" + FOLDER + "/" + service.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), FOLDER, NONELECTRONIC_REC));
+ //check record can't be shared
+ assertFalse("The record has been succesfully shared",
+ service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec2).getKey());
+ //check the error code when trying to share a record
+ assertEquals("The API response code is not " + HttpStatus.SC_INTERNAL_SERVER_ERROR, service.shareDocument(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nodeRefRec2).getValue(),
+ String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR));
+ }
+
+ @AfterClass
+ public void cleanupCategory() {
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, recordCategoryChild.getName());
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, category.getName());
+ deleteRecordCategory(category.getId());
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/AuditAccessTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/AuditAccessTests.java
new file mode 100644
index 0000000000..f2ad183915
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/AuditAccessTests.java
@@ -0,0 +1,211 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.core.v0.BaseAPI;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.audit.AuditEntry;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.RMAuditService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.model.UserModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.Test;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
+import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
+import static org.alfresco.rest.rm.community.model.audit.AuditEvents.DELETE_PERSON;
+import static org.alfresco.rest.rm.community.model.audit.AuditEvents.LOGIN_SUCCESSFUL;
+import static org.alfresco.rest.rm.community.records.SearchRecordsTests.*;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.junit.Assert.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+/**
+ * Audit Access tests
+ * @author Kavit Shah
+ */
+public class AuditAccessTests extends BaseRMRestTest {
+
+ private Optional deletedUser;
+ private final String TEST_PREFIX = generateTestPrefix(AuditAccessTests.class);
+ private static final String DELETE_USER_EVENT = "Delete User";
+ private final String record1 = TEST_PREFIX + "RM-2967 uploaded record";
+ private final String classifiedRecord = TEST_PREFIX + "RM-2967 classified record";
+ private final String folderName = TEST_PREFIX + "RM-2967 folder";
+ private final String categoryName = TEST_PREFIX + "RM-2967 category";
+ private final String editedCategoryName = "edited " + categoryName;
+ private final String editedFolderName = "edited " + folderName;
+ private final String editedRecordName = "edited " + record1;
+ private final String login_successfull = "Login Successful";
+ private RecordCategory categoryAll;
+
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+ @Autowired
+ private RMAuditService rmAuditService;
+
+ @Test(priority = 1)
+ @AlfrescoTest(jira = "RM-2967")
+ public void deleteRMUsersShowFullAuditTest() {
+
+ createTestPrecondition();
+ updateCategoryMetadata();
+ updateFolderMetadata();
+ updateRecordMetadata();
+
+ // delete record category and folder with rm_admin_deleted
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(deletedUser.get().getUsername(), deletedUser.get().getPassword(),
+ RM_SITE_ID, editedFolderName);
+ rmRolesAndActionsAPI.deleteAllItemsInContainer(deletedUser.get().getUsername(), deletedUser.get().getPassword(),
+ RM_SITE_ID, editedCategoryName);
+
+ // delete the user
+ Optional.of(deletedUser).ifPresent(x -> getDataUser().deleteUser(x.get()));
+
+ //check for RM-5235 fix
+ List auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getDataUser().usingAdmin().getAdminUser(),
+ DELETE_PERSON);
+
+ assertTrue("Delete user event not found in the audit log.", auditEntries.stream().anyMatch(
+ auditEntry -> auditEntry.getEvent().equals(DELETE_USER_EVENT)));
+ }
+
+
+ @Test(priority = 2)
+ public void filterEventsByLoginSuccessful()
+ {
+ createRMSiteIfNotExists();
+ List auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getDataUser().usingAdmin().getAdminUser(),
+ LOGIN_SUCCESSFUL);
+
+ assertFalse("Audit results should contain at least one Login Successful event",
+ auditEntries.isEmpty());
+
+ assertTrue("Audit results contain only Login Successful events",
+ auditEntries.stream()
+ .allMatch(e -> e.getEvent().startsWith(LOGIN_SUCCESSFUL.toString()) || e.getEvent().startsWith(login_successfull)));
+ }
+ /**
+ * Creates the required precondition for the test
+ *
+ * See Precondition in current class JavaDoc
+ */
+ private void createTestPrecondition() {
+ createRMSiteIfNotExists();
+
+ // create "rm deleted user" user if it does not exist and assign it to RM Administrator role
+ createDeletedUser();
+
+ // create category and folder
+ categoryAll = createCategoryIfDoesNotExist(categoryName,deletedUser.get());
+ createRecordFolderInCategory(folderName,categoryAll,deletedUser.get());
+ // upload an electronic record
+
+ recordsAPI.uploadElectronicRecord(deletedUser.get().getUsername(), deletedUser.get().getPassword(), getDefaultElectronicRecordProperties(record1), folderName, CMISUtil.DocumentType.TEXT_PLAIN);
+ // upload another electronic record and classify it
+ recordsAPI.uploadElectronicRecord(deletedUser.get().getUsername(), deletedUser.get().getPassword(), getDefaultElectronicRecordProperties(classifiedRecord), folderName, CMISUtil.DocumentType.TEXT_PLAIN);
+ }
+
+ private void createDeletedUser() {
+ // create Deleted User
+ deletedUser = Optional.ofNullable(getDataUser().createRandomTestUser());
+ rmRolesAndActionsAPI.assignRoleToUser(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ deletedUser.get().getUsername(),
+ ADMIN
+ );
+ }
+
+ private void updateCategoryMetadata() {
+ HashMap categoryProperties = new HashMap<>();
+ categoryProperties.put(BaseAPI.RMProperty.NAME, editedCategoryName);
+ categoryProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
+ categoryProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
+
+ // edit some category's properties
+ String categoryNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + categoryName);
+ rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), categoryNodeRef, categoryProperties);
+ }
+
+ private void updateFolderMetadata() {
+ HashMap folderProperties = new HashMap<>();
+ folderProperties.put(BaseAPI.RMProperty.NAME, editedFolderName);
+ folderProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
+ folderProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
+
+ // edit some folder's properties
+ String folderNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + editedCategoryName + "/" + folderName);
+ rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), folderNodeRef, folderProperties);
+ }
+
+ private void updateRecordMetadata() {
+ HashMap recordProperties = new HashMap<>();
+ recordProperties.put(BaseAPI.RMProperty.NAME, editedRecordName);
+ recordProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
+ recordProperties.put(BaseAPI.RMProperty.AUTHOR, "edited author");
+ recordProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
+
+ // edit some record's properties
+ String recordName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), editedFolderName, record1);
+ String recordNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + editedCategoryName + "/" + editedFolderName + "/" + recordName);
+ rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), recordNodeRef, recordProperties);
+ }
+
+
+ private RecordCategory createCategoryIfDoesNotExist(String CATEGORY_ALL, UserModel deletedUser) {
+ return createRootCategory(deletedUser, CATEGORY_ALL);
+ }
+
+ private RecordCategoryChild createRecordFolderInCategory(String FOLDER_SEARCH, RecordCategory recordCategory, UserModel deletedUser) {
+ return createFolder(deletedUser, recordCategory.getId(), FOLDER_SEARCH);
+ }
+
+ private Map getDefaultElectronicRecordProperties(String recordName) {
+ Map defaultProperties = new HashMap<>();
+ defaultProperties.put(BaseAPI.RMProperty.NAME, recordName);
+ defaultProperties.put(BaseAPI.RMProperty.TITLE, TITLE);
+ defaultProperties.put(BaseAPI.RMProperty.DESCRIPTION, DESCRIPTION);
+ defaultProperties.put(BaseAPI.RMProperty.CONTENT, TEST_CONTENT);
+ return defaultProperties;
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/BasicRulesIntegrationTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/BasicRulesIntegrationTests.java
new file mode 100644
index 0000000000..b8224a31e9
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/BasicRulesIntegrationTests.java
@@ -0,0 +1,104 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
+import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
+import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RulesAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.Test;
+
+
+import java.util.Collections;
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
+import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME;
+import static org.alfresco.rest.rm.community.base.TestData.NONELECTRONIC_RECORD_NAME;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.*;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.*;
+public class BasicRulesIntegrationTests extends BaseRMRestTest {
+
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ private final static String title = "Rule to complete";
+ private final static String description = "Rule to describe";
+ private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ @Autowired
+ private RulesAPI rulesAPI;
+
+ @Test
+ @AlfrescoTest(jira = "RM-2794")
+ public void basicRulesIntegration() {
+
+
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create RM Admin user");
+ rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
+ getAdminUser().getPassword(),
+ "Administrator");
+
+ STEP("Create record categories and record folders");
+ RecordCategory Category = createRootCategory(getRandomName("recordCategory"));
+ String recordFolder1 = createRecordFolder(Category.getId(), getRandomName("recFolder")).getId();
+
+
+ //create a rule for completing a record
+ RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
+ .applyToChildren(true).title(title)
+ .actions(Collections.singletonList(ActionsOnRule.COMPLETE_RECORD.getActionValue()));
+ rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + Category.getId(), ruleDefinition);
+
+ RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
+
+ //create two electronic record in record folder
+ String electronicRecordId1 = createElectronicRecord(recordFolder1, ELECTRONIC_RECORD_NAME).getId();
+ String electronicRecordId2 = createElectronicRecord(recordFolder1, ELECTRONIC_RECORD_NAME).getId();
+ assertStatusCode(CREATED);
+
+
+
+ // Update the rules for record Category
+ rulesAPI.updateRule(getAdminUser().getUsername(), getAdminUser().getPassword(),
+ NODE_PREFIX + Category.getId(), ruleDefinition.description("description").id(description));
+
+ //Delete the root category and rules
+ deleteRecordCategory(Category.getId());
+ rulesAPI.deleteAllRulesOnContainer(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + Category.getId());
+ }
+
+
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateCategoriesTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateCategoriesTests.java
new file mode 100644
index 0000000000..38a0e111ad
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateCategoriesTests.java
@@ -0,0 +1,125 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
+import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.junit.Assert.assertFalse;
+import static org.springframework.http.HttpStatus.OK;
+import static org.testng.Assert.assertEquals;
+
+public class CreateCategoriesTests extends BaseRMRestTest {
+
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ private RecordCategory rootCategory;
+ private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private RecordCategory Category1;
+ private RecordCategory Category2;
+ private RecordCategory SubCategory1;
+ private RecordCategory SubCategory2;
+
+ @BeforeClass(alwaysRun = true)
+ public void preconditionForCreateCategoriesTests()
+ {
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create RM Admin user");
+ rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
+ getAdminUser().getPassword(),
+ "Administrator");
+
+ STEP("Create two category");
+ Category1 = createRootCategory(getRandomName("Category1"));
+
+ Category2= createRootCategory(getRandomName("Category2"));
+
+ STEP("Create Sub category");
+ RecordCategoryChild subCategory1 = createRecordCategory(Category1.getId(), getRandomName("subCategory1"));
+ RecordCategoryChild subCategory2 = createRecordCategory(Category2.getId(), getRandomName("subCategory2"));
+
+ }
+
+
+ @Test @AlfrescoTest(jira = "RM-2756")
+ public void createCategories() throws Exception {
+
+ FilePlan filePlan = getRestAPIFactory().getFilePlansAPI().getFilePlan(FILE_PLAN_ALIAS);
+
+ STEP("copy category 1 to File Plan.");
+ getRestAPIFactory().getNodeAPI(toContentModel(Category1.getId())).copy(createBodyForMoveCopy(filePlan.getId()));
+
+ STEP("copy category 1 to category 2");
+ getRestAPIFactory().getNodeAPI(toContentModel(Category1.getId())).copy(createBodyForMoveCopy(Category2.getId()));
+
+ String categoryName = "Category name " + getRandomAlphanumeric();
+ String categoryTitle = "Category title " + getRandomAlphanumeric();
+
+
+ // Create the root record category
+ RecordCategory Category1 = createRootCategory(categoryName, categoryTitle);
+
+ String newCategoryName = "Rename " + categoryName;
+
+ // Build the properties which will be updated
+ RecordCategory recordCategoryUpdated = Category1.builder().name(newCategoryName).build();
+
+ // Update the record category
+ RecordCategory renamedRecordCategory = getRestAPIFactory().getRecordCategoryAPI().updateRecordCategory(recordCategoryUpdated,Category1.getId());
+ // Verify the status code
+ assertStatusCode(OK);
+
+ // verify renamed component and editTitle component still has this parent
+ assertEquals(renamedRecordCategory.getParentId(), filePlan.getId());
+
+ STEP("move category 1 edited copy to File Plan");
+ getRestAPIFactory().getNodeAPI(toContentModel(renamedRecordCategory.getId())).move(createBodyForMoveCopy(filePlan.getId()));
+ assertStatusCode(OK);
+
+ // delete All the categories
+ deleteRecordCategory(Category1.getId());
+ deleteRecordCategory(Category2.getId());
+ }
+}
\ No newline at end of file
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateFoldersTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateFoldersTests.java
new file mode 100644
index 0000000000..35335584d9
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/CreateFoldersTests.java
@@ -0,0 +1,147 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.common.ReviewPeriod;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderProperties;
+import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
+import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
+import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.*;
+
+public class CreateFoldersTests extends BaseRMRestTest {
+
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+
+ private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private RecordCategory Category1;
+ private RecordCategory Category2;
+ private RecordCategoryChild recordCategoryChild;
+
+ @BeforeClass(alwaysRun = true)
+ public void preconditionForCreateFolderTests() {
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create RM Admin user");
+ rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
+ getAdminUser().getPassword(),
+ "Administrator");
+
+ STEP("Create two category");
+ Category1 = createRootCategory(getRandomName("Category1"));
+
+ Category2 = createRootCategory(getRandomName("Category2"));
+
+ // Create a record folder inside the category 1
+ recordCategoryChild = createRecordFolder(Category1.getId(), getRandomName("recFolder"));
+
+ }
+
+ @Test
+ @AlfrescoTest(jira = "RM-2757")
+ public void createFolders() throws Exception {
+
+ // Create record category first
+ String folderDescription = "The folder description is updated" + getRandomAlphanumeric();
+ String folderName = "The folder name is updated" + getRandomAlphanumeric();
+ String folderTitle = "Update title " + getRandomAlphanumeric();
+ String location = "Location "+ getRandomAlphanumeric();
+
+ // Create the record folder properties to update
+ RecordFolder recordFolder = RecordFolder.builder()
+ .name(folderName)
+ .properties(RecordFolderProperties.builder()
+ .title(folderTitle)
+ .description(folderDescription)
+ .vitalRecordIndicator(true)
+ .reviewPeriod(new ReviewPeriod("month","1"))
+ .location(location)
+ .build())
+ .build();
+
+ // Update the record folder
+ RecordFolder updatedRecordFolder = getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(recordFolder, recordCategoryChild.getId());
+
+ // Check the Response Status Code
+ assertStatusCode(OK);
+
+ STEP("copy updated Record in category 1 and category 2");
+ getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).copy(createBodyForMoveCopy(Category1.getId()));
+ //assertStatusCode(OK);
+ getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).copy(createBodyForMoveCopy(Category2.getId()));
+ //assertStatusCode(OK);
+
+
+ // Delete the Updated folder
+ RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
+ String recordFolderId = updatedRecordFolder.getId();
+ recordFolderAPI.deleteRecordFolder(recordFolderId);
+
+ // Check the response status code
+ assertStatusCode(NO_CONTENT);
+
+ // Check the record folder is not found
+ recordFolderAPI.getRecordFolder(recordFolderId);
+
+ // Check the response status code
+ assertStatusCode(NOT_FOUND);
+
+ STEP("move updated Record from category 1 to category 2");
+ getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).move(createBodyForMoveCopy(Category2.getId()));
+
+ // move category 2 to category 1
+ getRestAPIFactory().getNodeAPI(toContentModel(Category2.getId())).move(createBodyForMoveCopy(Category1.getId()));
+
+ // Delete the record category
+ RecordCategoryAPI recordCategoryAPI = getRestAPIFactory().getRecordCategoryAPI();
+ String recordCategoryId = Category1.getId();
+ recordCategoryAPI.deleteRecordCategory(recordCategoryId);
+
+ // Verify the status code
+ assertStatusCode(NO_CONTENT);
+
+ }
+
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DeclareDocsAsRecordsOnUpdateRuleNewVersionTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DeclareDocsAsRecordsOnUpdateRuleNewVersionTests.java
new file mode 100644
index 0000000000..f4bcd7a7b5
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DeclareDocsAsRecordsOnUpdateRuleNewVersionTests.java
@@ -0,0 +1,122 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import lombok.Getter;
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
+import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildEntry;
+import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
+import org.alfresco.rest.v0.RulesAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.data.DataContent;
+import org.alfresco.utility.data.DataSite;
+import org.alfresco.utility.data.DataUserAIS;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.FolderModel;
+import org.alfresco.utility.model.SiteModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static lombok.AccessLevel.PROTECTED;
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.CREATED;
+
+public class DeclareDocsAsRecordsOnUpdateRuleNewVersionTests extends BaseRMRestTest {
+
+
+ @Autowired
+ private DataSite dataSite;
+ private SiteModel publicSite;
+ private RecordCategory recordCategory;
+ @Autowired
+ private RulesAPI rulesAPI;
+ @Autowired
+ protected DataContent dataContent;
+ @Autowired
+ @Getter(value = PROTECTED)
+ protected DataUserAIS dataUser;
+ private final static String title = "Rule to convert document as record";
+
+ @BeforeClass (alwaysRun = true)
+ public void setUp()
+ {
+ publicSite = dataSite.usingAdmin().createPublicRandomSite();
+ recordCategory = createRootCategory(getRandomName("recordCategory"));
+
+ }
+
+ @Test
+ @AlfrescoTest(jira = "RM-1521")
+ public void declareDocsAsRecordsOnUpdateRuleNewVersion() {
+ FolderModel testFolder;
+
+ STEP("Create test collaboration site to store documents in.");
+ publicSite = dataSite.usingAdmin().createPublicRandomSite();
+
+ STEP("Create a record folder with a DECLARE_AS_RECORD");
+ RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
+ RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
+ .applyToChildren(true)
+ .actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
+ rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
+
+ STEP("Create a document in the collaboration site");
+ FileModel testFile = dataContent.usingSite(publicSite)
+ .usingAdmin()
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+ assertStatusCode(CREATED);
+
+
+ // verify the declared record is in Unfilled Records folder
+ UnfiledContainerAPI unfiledContainersAPI = getRestAPIFactory().getUnfiledContainersAPI();
+ List matchingRecords = unfiledContainersAPI.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
+ .getEntries()
+ .stream()
+ .filter(e -> e.getEntry().getId().equals(testFile.getNodeRefWithoutVersion()))
+ .collect(Collectors.toList());
+
+ //delete rm items
+ deleteRecordCategory(recordCategory.getId());
+ STEP("Delete the record.");
+ //delete created collaboration site
+ dataSite.deleteSite(publicSite);
+
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DestroyRecordFolderActionsTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DestroyRecordFolderActionsTest.java
new file mode 100644
index 0000000000..a3f35e5423
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DestroyRecordFolderActionsTest.java
@@ -0,0 +1,121 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.OK;
+import static org.testng.AssertJUnit.assertNotNull;
+
+
+public class DestroyRecordFolderActionsTest extends BaseRMRestTest {
+
+ private RecordCategory Category1,CATEGORY_TO_MOVE;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ private final String TEST_PREFIX = generateTestPrefix(DestroyRecordFolderActionsTest.class);
+ private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
+
+
+ @BeforeClass(alwaysRun = true)
+ private void setUp(){
+
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create two record category");
+ Category1 = createRootCategory(getRandomName("Category1"));
+ CATEGORY_TO_MOVE = createRootCategory(getRandomName("CATEGORY_TO_MOVE"));
+
+ //create retention schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
+
+ // add destroy step with ghosting
+ dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
+
+ }
+
+ @Test
+ @AlfrescoTest (jira = "RM-1621")
+ public void moveOnCutOffDestroyFolders() throws Exception {
+
+ //create folders
+ RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ // edit disposition date
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
+
+ // cut off the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
+
+
+ // Destroy the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
+
+
+ //Move the FOLDER_DESTROY within the CATEGORY_TO_MOVE.");
+ getRestAPIFactory().getNodeAPI(toContentModel(FOLDER_DESTROY.getId())).move(createBodyForMoveCopy(CATEGORY_TO_MOVE.getId()));
+ assertStatusCode(OK);
+
+ }
+
+ @AfterMethod(alwaysRun = true)
+ private void deletePreconditions() {
+
+ deleteRecordCategory(Category1.getId());
+ deleteRecordCategory(CATEGORY_TO_MOVE.getId());
+
+ }
+
+ }
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DispositionScheduleLinkedRecordsTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DispositionScheduleLinkedRecordsTest.java
new file mode 100644
index 0000000000..b1badc40c5
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/DispositionScheduleLinkedRecordsTest.java
@@ -0,0 +1,425 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.core.v0.RMEvents;
+import org.alfresco.rest.model.RestNodeBodyMoveCopyModel;
+import org.alfresco.rest.model.RestNodeModel;
+import org.alfresco.rest.requests.Node;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.user.UserRoles;
+import org.alfresco.rest.v0.LinksAPI;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.model.RepoTestModel;
+import org.alfresco.utility.model.UserModel;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.AssertJUnit;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_REF_WORKSPACE_SPACES_STORE;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.CUT_OFF_ASPECT;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.*;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.http.HttpStatus.NO_CONTENT;
+
+public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private LinksAPI linksAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ private final static String TEST_PREFIX = generateTestPrefix(DispositionScheduleLinkedRecordsTest.class);
+ private RecordCategory Category1,catsameLevel1,catsameLevel2;
+ private RecordCategoryChild CopyCatFolder,folder1,CatFolder,folder2;
+ private static final String categoryRM3077 = TEST_PREFIX + "RM-3077_manager_sees_me";
+ private static final String copyCategoryRM3077 = "Copy_of_" + categoryRM3077;
+ private static final String folderRM3077 = "RM-3077_folder_"+ categoryRM3077;
+ private static final String copyFolderRM3077 = "Copy_of_" + folderRM3077;
+ private final String electronicRecord = "RM-2937 electronic 2 record";
+ private final String folder = TEST_PREFIX + "RM-2937 folder ghosting";
+ private static final String categoryRecordsRM2526 = TEST_PREFIX + "RM-2526_category_records_immediately";
+ private static final String category2RecordsRM2526 = TEST_PREFIX + "RM-2526_category_2_records_1_day";
+ private static final String firstCategoryRM3060 = TEST_PREFIX + "RM-3060_category_record";
+ private static final String secondCategoryRM3060 = "Copy_of_" + firstCategoryRM3060;
+ private static final String firstFolderRM3060 = TEST_PREFIX + "RM-3060_folder";
+ private static final String secondFolderRM3060 = TEST_PREFIX + "RM-3060_disposition_on_Record_Level";
+ private static final String electronicRecordRM3060 = TEST_PREFIX + "RM-3060_electronic_1_record";
+ private static final String nonElectronicRecordRM3060 = TEST_PREFIX + "RM-3060_non-electronic_record";
+ private static final String TRANSFER_LOCATION = TEST_PREFIX + "RM-3060_transferred_records";
+ public static final String TRANSFER_TYPE = "rma:transferred";
+ private FilePlan filePlanModel;
+ private UserModel rmAdmin, rmManager;
+ @BeforeClass(alwaysRun = true)
+ public void setupDispositionScheduleLinkedRecordsTest() {
+ createRMSiteIfNotExists();
+ //get file plan
+ filePlanModel = getRestAPIFactory().getFilePlansAPI().getFilePlan(FILE_PLAN_ALIAS);
+
+ // create "rm admin" user if it does not exist and assign it to RM Administrator role
+ rmAdmin = getDataUser().createRandomTestUser();
+ rmRolesAndActionsAPI.assignRoleToUser(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),rmAdmin.getUsername(),
+ UserRoles.ROLE_RM_ADMIN.roleId);
+
+ // create "rm Manager" user if it does not exist and assign it to RM Administrator role
+ rmManager = getDataUser().createRandomTestUser();
+ rmRolesAndActionsAPI.assignRoleToUser(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),rmManager.getUsername(),
+ UserRoles.ROLE_RM_MANAGER.roleId);
+ }
+ /**
+ * Disposition Schedule on Record Folder with linked records test
+ *
+ * Precondition:
+ *
+ * Create rm_manager user that would have RM Managers role, rm_admin that would have RM Administrator role.
+ * Log in with admin user, create a category "manager sees me", give rm_manager read&file permission over it.
+ * Create a disposition schedule for it that would cut off folders after 1 day from created date. Copy the category.
+ *
+ *
TestRail Test C775
+ **/
+ @Test
+ @AlfrescoTest(jira = "RM-1622")
+ public void dispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
+ STEP("Create record category");
+ Category1 = createRootCategory(categoryRM3077);
+
+ //create retention schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
+
+ //create a copy of the category recordsCategory
+ String CopyCategoryId = copyCategory(getAdminUser(),Category1.getId(), copyCategoryRM3077);
+
+ // create folders in both categories
+ CatFolder = createRecordFolder(Category1.getId(), folderRM3077);
+ CopyCatFolder = createRecordFolder(CopyCategoryId, copyFolderRM3077);
+
+ // create record files
+ String electronicRecord = "RM-2801 electronic record";
+ Record elRecord = createElectronicRecord(CatFolder.getId(), electronicRecord);
+ String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), electronicRecord);
+
+ String nonElectronicRecord = "RM-2801 non-electronic record";
+ Record nonElRecord = createNonElectronicRecord(CatFolder.getId(), nonElectronicRecord);
+ String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), nonElectronicRecord);
+
+ // link the records to copy folder, then complete them
+ List recordLists = new ArrayList<>();
+ recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + elRecord.getId());
+ recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + nonElRecord.getId());
+
+ linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,copyCategoryRM3077 + "/" +
+ copyFolderRM3077, recordLists);
+ recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), elRecordFullName);
+ recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), nonElRecordFullName);
+
+ // edit disposition date
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),CatFolder.getName());
+
+ // cut off the Folder
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),CatFolder.getName());
+
+ // Verify the Content
+ Node electronicNode = getNode(elRecord.getId());
+ assertTrue("The content of " + electronicRecord + " is available",
+ StringUtils.isEmpty(electronicNode.getNodeContent().getResponse().getBody().asString()));
+
+ // verify the Properties
+ AssertJUnit.assertNull("The properties are present even after cutting off the record.", elRecord.getProperties().getTitle());
+
+ // delete precondition
+ deleteRecordCategory(Category1.getId());
+ deleteRecordCategory(CopyCategoryId);
+ }
+ /**
+ * Test covering RM-3060
+ * Check the disposition steps for a record can be executed
+ * When the record is linked to a folder with the same disposition schedule
+ * */
+ @Test
+ @AlfrescoTest (jira = "RM-3060")
+ public void sameDispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
+
+ // create a category with retention applied on records level
+ RecordCategory recordCategory = getRestAPIFactory().getFilePlansAPI(rmAdmin)
+ .createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
+ RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
+ dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
+ dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "week|1", DATE_FILED);
+ dispositionScheduleService.addTransferAfterEventStep(firstCategoryRM3060, TRANSFER_LOCATION, RMEvents.CASE_CLOSED.getEventName());
+ dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(firstCategoryRM3060, "week|1", CUT_OFF_DATE);
+
+ // make a copy of the category created
+ String categorySecondId = copyCategory(getAdminUser(), recordCategory.getId(), secondCategoryRM3060);
+
+ // create a folder on the category firstCategoryRM3060 with a complete electronic record
+ RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(recordCategory.getId(),firstFolderRM3060);
+ Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
+
+ String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
+ String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
+
+ recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), elRecordFullName);
+
+ // create a folder on the category secondCategoryRM3060 with a non electronic record
+ RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(categorySecondId,secondFolderRM3060);
+ Record secondNonElectronicRecord = createNonElectronicRecord(secondFolderRecordCategoryChild.getId(),nonElectronicRecordRM3060);
+
+ // link the nonElectronicRecordRM3060 to firstFolderRM3060
+ List recordLists = new ArrayList<>();
+ recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
+
+ linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
+ secondFolderRM3060, recordLists);
+ String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), secondFolderRM3060, secondNonElectronicRecord.getName());
+ String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060);
+
+ // complete records and cut them off
+ recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), nonElRecordFullName);
+
+ // edit the disposition date
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
+
+ // cut off the record
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
+
+ //check the record is cut off
+ AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
+
+ // link the electronic record to secondFolderRM3060
+ recordLists.clear();
+ recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
+ linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
+ secondFolderRM3060, recordLists);
+
+ // edit the disposition date and cut off the record
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
+
+ AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
+
+ // open the record and complete the disposition schedule event
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), elRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), nonElRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
+
+ // transfer the files & complete transfers
+ HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060));
+
+ String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
+
+ HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060));
+
+ String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
+
+ AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully transferred", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
+ AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully transferred.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
+
+ // edit the disposition date for nonElectronicRecordRM3060 & electronicRecordRM3060
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
+
+ // destroy nonElectronicRecordRM3060 & electronicRecordRM3060 records
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
+
+ // check the file is not displayed
+ assertNull("The file " + nonElectronicRecordRM3060 + " has not been successfully destroyed.", secondNonElectronicRecord.getContent());
+ assertNull("The file " + electronicRecordRM3060 + " has not been successfully destroyed.", firstElectronicRecord.getContent());
+
+ // delete precondition
+ deleteRecordCategory(recordCategory.getId());
+ deleteRecordCategory(categorySecondId);
+ }
+ private String copyCategory(UserModel user, String categoryId, String copyName) {
+ RepoTestModel repoTestModel = new RepoTestModel() {};
+ repoTestModel.setNodeRef(categoryId);
+ RestNodeModel restNodeModel;
+
+ RestNodeBodyMoveCopyModel copyDestinationInfo = new RestNodeBodyMoveCopyModel();
+ copyDestinationInfo.setTargetParentId(filePlanModel.getId());
+ copyDestinationInfo.setName(copyName);
+
+ try
+ {
+ restNodeModel = getRestAPIFactory().getNodeAPI(user, repoTestModel).copy(copyDestinationInfo);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Problem copying category.", e);
+ }
+ return restNodeModel.getId();
+ }
+
+ private Node getNode(String recordId)
+ {
+ RepoTestModel repoTestModel = new RepoTestModel() {};
+ repoTestModel.setNodeRef(recordId);
+ return getRestAPIFactory().getNodeAPI(repoTestModel);
+ }
+
+ private String getTransferId(HttpResponse httpResponse,String nodeRef) {
+ HttpEntity entity = httpResponse.getEntity();
+ String responseString = null;
+ try {
+ responseString = EntityUtils.toString(entity, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ JSONObject result = new JSONObject(responseString);
+ return result
+ .getJSONObject("results")
+ .get(nodeRef)
+ .toString();
+
+ }
+
+ @Test
+ @AlfrescoTest(jira = "RM-1622")
+ public void sameLevelDispositionScheduleStepsPeriodsCalculation() throws Exception {
+
+ // create a category with retention applied on records level
+ RecordCategory catsameLevel1 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
+ .createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
+ RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
+ RecordCategory catsameLevel2 = getRestAPIFactory().getFilePlansAPI(rmAdmin)
+ .createRootRecordCategory(RecordCategory.builder().name(secondCategoryRM3060).build(),
+ RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
+
+ // create retention schedule applied on records for category 1
+ dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
+
+ // with retain immediately after record creation date and cut 1 day after record creation date
+ dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "day|1", DATE_FILED);
+
+
+ // create a folder on the category firstCategoryRM3060 with a complete electronic record
+ RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(catsameLevel1.getId(),firstFolderRM3060);
+ Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
+
+ String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
+ String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
+
+ recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), elRecordFullName);
+
+ // create a folder on the category secondCategoryRM3060 with a non electronic record
+ RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(catsameLevel2.getId(),secondFolderRM3060);
+ String elRecordNameNodeRefs = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
+
+
+ // link it to the folder in second category through the details page
+ List recordLists = new ArrayList<>();
+ recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + firstElectronicRecord.getId());
+
+ linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
+ getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
+ secondFolderRM3060, recordLists);
+
+ // edit disposition date
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRefs);
+
+
+ }
+
+ @Test (dependsOnMethods = {"sameLevelDispositionScheduleStepsPeriodsCalculation" })
+ public void deleteLongestPeriodTestPrecondition() {
+ // Delete the RM site
+ getRestAPIFactory().getRMSiteAPI().deleteRMSite();
+
+ // Verify the status code
+ assertStatusCode(NO_CONTENT);
+ }
+ }
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileAsRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileAsRecordTests.java
new file mode 100644
index 0000000000..cdadcd5ceb
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileAsRecordTests.java
@@ -0,0 +1,238 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderCollection;
+import org.alfresco.rest.rm.community.model.user.UserRoles;
+import org.alfresco.rest.v0.RecordCategoriesAPI;
+import org.alfresco.rest.v0.service.RoleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.alfresco.utility.data.DataContent;
+import org.alfresco.utility.data.DataSite;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.FileType;
+import org.alfresco.utility.model.SiteModel;
+import org.alfresco.utility.model.UserModel;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import java.util.concurrent.atomic.AtomicReference;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
+import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+import static org.testng.Assert.*;
+
+public class FileAsRecordTests extends BaseRMRestTest {
+
+ private static final String CATEGORY_MANAGER = "catManager" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String CATEGORY_ADMIN = "catAdmin" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String FOLDER_MANAGER = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String FOLDER_ADMIN = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
+
+ private UserModel nonRMuser,rmManager;
+ private SiteModel testSite;
+ private FileModel document, documentDeclared;
+ private RecordCategory category_manager, category_admin;
+ private RecordCategoryChild folder_admin, folder_manager ;
+ @Autowired
+ private DataSite dataSite;
+ @Autowired
+ private DataContent dataContent;
+ @Autowired
+ private RoleService roleService;
+ @Autowired
+ private RecordCategoriesAPI recordCategoriesAPI;
+ /**
+ * Create preconditions:
+ *
+ * 1. RM site is created
+ * 2. Two users: user without RM role and a user with RM manager role
+ * 3. Two Record categories with one folder each
+ * 4. User with RM MANAGER role has Filling permission over one category
+ *
+ */
+ @BeforeClass(alwaysRun = true)
+ public void preconditionForFileAsRecordRecordTests()
+ {
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create a user");
+ nonRMuser = dataUser.createRandomTestUser("testUser");
+
+ STEP("Create a collaboration site");
+ testSite = dataSite.usingUser(nonRMuser).createPublicRandomSite();
+
+ STEP("Create a document with the user without RM role");
+ document = dataContent.usingSite(testSite)
+ .usingUser(nonRMuser)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ STEP("Create two categories with two folders");
+ category_manager = createRootCategory(CATEGORY_MANAGER);
+ category_admin = createRootCategory(CATEGORY_ADMIN);
+ folder_admin = createFolder(category_admin.getId(),FOLDER_ADMIN);
+ folder_manager = createFolder(category_manager.getId(),FOLDER_MANAGER);
+
+ STEP("Create an rm user and give filling permission over CATEGORY_MANAGER record category");
+ RecordCategory recordCategory = new RecordCategory().builder()
+ .id(category_manager.getId())
+ .build();
+ rmManager = roleService.createCollaboratorWithRMRoleAndPermission(testSite, recordCategory,
+ UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
+ }
+
+ /**
+ * Given I have selected the record folder I want to file my declared record to
+ * When I confirm the action
+ * Then the dialog closes
+ * And the document is now shown as a record in the collaboration site
+ * And if I navigated to the record folder, as any user who had the right permissions, then I would see the
+ * record filed
+ */
+ @Test
+ @AlfrescoTest(jira = "RM-6780")
+ public void checkFileAsRecordToRecordFolder() throws Exception {
+
+ AtomicReference apiChildren = new AtomicReference<>();
+ STEP("Create a document with the user with RM role");
+ documentDeclared = dataContent.usingSite(testSite).usingUser(rmManager)
+ .createContent(new FileModel("checkDeclareAndFileToRecordFolder", FileType.TEXT_PLAIN));
+
+ STEP("Declare and file into a record folder the document uploaded");
+
+ getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(documentDeclared,
+ Utility.buildPath(CATEGORY_MANAGER, FOLDER_MANAGER));
+
+ STEP("Check the file is a record within the collaboration site");
+
+ try
+ {
+ Utility.sleep(1000, 40000, () ->
+ {
+ JSONObject collaboratorSearchJson = getSearchApi().liveSearchForDocuments(rmManager.getUsername(),
+ rmManager.getPassword(),
+ documentDeclared.getName());
+ assertTrue("Rm Manager not able to find the document.", collaboratorSearchJson.getJSONArray("items").length() != 0);
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ STEP("Check the record is filed into the record folder.");
+ // Get children from API
+ // List children from API
+ try
+ {
+ Utility.sleep(1000, 40000, () ->
+ {
+ apiChildren.set((RecordFolderCollection) getRestAPIFactory()
+ .getRecordFolderAPI(rmManager).getRecordFolderChildren(folder_manager.getId(), "include=properties")
+ .assertThat().entriesListIsNotEmpty().assertThat().entriesListIsNotEmpty());
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fail("InterruptedException received while waiting for results.");
+ }
+
+ assertEquals(apiChildren.get()
+ .getEntries()
+ .get(0)
+ .getEntry()
+ .getProperties()
+ .getOriginalName(),documentDeclared.getName());
+ }
+
+ /**
+ * Given I have selected the "File As Record" action
+ * When I confirm the action without selecting a location to file to
+ * Then the record is declared in the unfiled folder
+ */
+ @Test
+ @AlfrescoTest (jira = "RM-6780")
+ public void fileAsRecordToUnfiledRecordFolder() throws Exception {
+ STEP("Create a document with the user without RM role");
+ FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(rmManager)
+ .createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
+ FileType.TEXT_PLAIN));
+
+ STEP("Click on Declare and file without selecting a record folder");
+ getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(inplaceRecord,"");
+
+ STEP("Check the file is declared in unfiled record folder");
+ Assert.assertTrue(isMatchingRecordInUnfiledRecords(inplaceRecord), "Record should be filed to Unfiled Records folder");
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void cleanUpForFileAsRecordRecordTests() {
+ STEP("Delete the collaboration site");
+ dataSite.usingUser(nonRMuser).deleteSite(testSite);
+
+ STEP("Empty the trashcan.");
+ restClient.authenticateUser(nonRMuser).withCoreAPI().usingTrashcan().deleteNodeFromTrashcan(toContentModel(testSite.getId()));
+
+ getRestAPIFactory()
+ .getUnfiledContainersAPI(rmManager)
+ .getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
+ .getEntries()
+ .stream()
+ .forEach(x -> getRestAPIFactory()
+ .getRecordsAPI()
+ .deleteRecord(x.getEntry().getId()));
+
+ STEP("Cleanup Documents inside folders");
+
+ STEP("Delete folders");
+ getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(folder_admin.getId());
+ getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(folder_manager.getId());
+
+ STEP("Delete categories");
+ recordCategoriesAPI.deleteCategory(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), category_manager.getName());
+ recordCategoriesAPI.deleteCategory(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), category_admin.getName());
+
+ STEP("Delete Users");
+ dataUser.deleteUser(nonRMuser);
+ dataUser.deleteUser(rmManager);
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileVersionAsRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileVersionAsRecordTests.java
new file mode 100644
index 0000000000..09600f9545
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FileVersionAsRecordTests.java
@@ -0,0 +1,138 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.dataprep.CMISUtil;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderCollection;
+import org.alfresco.rest.rm.community.model.user.UserRoles;
+import org.alfresco.rest.rm.community.records.FileUnfiledRecordsTests;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordCategoriesAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.RoleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.alfresco.utility.data.DataContent;
+import org.alfresco.utility.data.DataSite;
+import org.alfresco.utility.model.FileModel;
+import org.alfresco.utility.model.FileType;
+import org.alfresco.utility.model.SiteModel;
+import org.alfresco.utility.model.UserModel;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class FileVersionAsRecordTests extends BaseRMRestTest {
+
+ private UserModel nonRMuser,rmManager;
+ private SiteModel testSite;
+ private FileModel document, documentDeclared;
+ private RecordCategory category_manager, category_admin;
+ private RecordCategoryChild folder_admin, folder_manager ;
+ private static final String CATEGORY_MANAGER = "catManager" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String CATEGORY_ADMIN = "catAdmin" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String FOLDER_MANAGER = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
+ private static final String FOLDER_ADMIN = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
+
+ @Autowired
+ private DataSite dataSite;
+ @Autowired
+ private DataContent dataContent;
+ @Autowired
+ private RoleService roleService;
+
+ @BeforeClass(alwaysRun = true)
+ public void preconditionForFileVersionAsRecordTests()
+ {
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create a user");
+ nonRMuser = dataUser.createRandomTestUser("testUser");
+
+ STEP("Create a collaboration site");
+ testSite = dataSite.usingUser(nonRMuser).createPublicRandomSite();
+
+ STEP("Create a document with the user without RM role");
+ document = dataContent.usingSite(testSite)
+ .usingUser(nonRMuser)
+ .createContent(CMISUtil.DocumentType.TEXT_PLAIN);
+
+ STEP("Create two categories with two folders");
+ category_manager = createRootCategory(CATEGORY_MANAGER);
+ category_admin = createRootCategory(CATEGORY_ADMIN);
+ folder_admin = createFolder(category_admin.getId(),FOLDER_ADMIN);
+ folder_manager = createFolder(category_manager.getId(),FOLDER_MANAGER);
+
+ STEP("Create an rm user and give filling permission over CATEGORY_MANAGER record category");
+ RecordCategory recordCategory = new RecordCategory().builder()
+ .id(category_manager.getId())
+ .build();
+ rmManager = roleService.createCollaboratorWithRMRoleAndPermission(testSite, recordCategory,
+ UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
+
+ }
+
+ @Test
+ @AlfrescoTest (jira = "APPS-1625")
+ public void fileVersionAsRecordToUnfiledRecordContainer() throws Exception
+ {
+
+ AtomicReference apiChildren = new AtomicReference<>();
+
+ STEP("Create a document with the user without RM role");
+ FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(rmManager)
+ .createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
+ FileType.TEXT_PLAIN));
+
+ STEP("Click on Declare and file without selecting a record folder");
+ getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(inplaceRecord,"");
+
+ STEP("Check the file is declared in unfiled record folder");
+ Assert.assertTrue(isMatchingRecordInUnfiledRecords(inplaceRecord), "Record should be filed to Unfiled Records folder");
+
+
+ }
+
+
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleTests.java
new file mode 100644
index 0000000000..e2a9d7c6da
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleTests.java
@@ -0,0 +1,108 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+
+public class FoldersDispositionScheduleTests extends BaseRMRestTest {
+
+ private RecordCategory Category1;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ private final String TEST_PREFIX = generateTestPrefix(FoldersDispositionScheduleTests.class);
+ private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
+ private final String electronicRecord = "RM-2937 electronic 2 record";
+ private final String nonElectronicRecord = "RM-2937 non-electronic record";
+
+ @BeforeClass(alwaysRun = true)
+ private void setUp(){
+
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create record category");
+ Category1 = createRootCategory(getRandomName("Title"));
+ }
+
+ @Test
+ @AlfrescoTest (jira = "RM-2937")
+ public void foldersDispositionScheduleWithGhosting() {
+
+ //create retention schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
+
+ // add destroy step with ghosting
+ dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
+
+ //create folders
+ RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(),electronicRecord);
+ Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(),nonElectronicRecord);
+
+ // complete records
+ completeRecord(elRecord.getId());
+ completeRecord(nonElRecord.getId());
+
+ // edit disposition date
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
+
+ // cut off the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
+
+ // Destroy the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
+ }
+
+ @AfterMethod(alwaysRun = true)
+ private void deletePreconditions() {
+ deleteRecordCategory(Category1.getId());
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleWithoutGhostRecordTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleWithoutGhostRecordTests.java
new file mode 100644
index 0000000000..4bec2fd08c
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/FoldersDispositionScheduleWithoutGhostRecordTests.java
@@ -0,0 +1,116 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+
+public class FoldersDispositionScheduleWithoutGhostRecordTests extends BaseRMRestTest {
+
+ private RecordCategory Category1;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ private final String TEST_PREFIX = generateTestPrefix(FoldersDispositionScheduleWithoutGhostRecordTests.class);
+ private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
+ private final String electronicRecord = "RM-2937 electronic 2 record";
+ private final String nonElectronicRecord = "RM-2937 non-electronic record";
+
+ @BeforeClass(alwaysRun = true)
+ private void setUp(){
+
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create record category");
+ Category1 = createRootCategory(getRandomName("Title"));
+ }
+
+ @Test
+ @AlfrescoTest(jira="RM-2937")
+ public void foldersDispositionScheduleWithoutGhosting() {
+
+ //create retention schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
+
+ // add destroy step with ghosting
+ dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(Category1.getName(), "day|1", CUT_OFF_DATE);
+
+ //create folders
+ RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(),electronicRecord);
+ Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(),nonElectronicRecord);
+
+ // complete records
+ completeRecord(elRecord.getId());
+ completeRecord(nonElRecord.getId());
+
+ // edit disposition date
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
+
+ // cut off the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
+
+ // edit disposition date
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
+
+ Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
+
+ // Destroy the FOLDER_DESTROY
+ recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
+ }
+
+ @AfterMethod(alwaysRun = true)
+ private void deletePreconditions() {
+ deleteRecordCategory(Category1.getId());
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordRetentionAsOfDateTest.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordRetentionAsOfDateTest.java
new file mode 100644
index 0000000000..5427019983
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordRetentionAsOfDateTest.java
@@ -0,0 +1,156 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.core.v0.BaseAPI;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordCategoriesAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.apache.commons.lang3.time.DateUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.testng.Assert.assertTrue;
+
+public class RecordRetentionAsOfDateTest extends BaseRMRestTest {
+
+ /** data prep 6services */
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ @Autowired
+ private RecordCategoriesAPI recordCategoriesAPI;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ private RecordCategory Category1;
+ private final String TEST_PREFIX = generateTestPrefix(RecordRetentionAsOfDateTest.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private final String recordsCategory = TEST_PREFIX + "RM-5733 category";
+ private final String folderDisposition = TEST_PREFIX + "RM-5733 folder";
+
+ private static final String YEAR_MONTH_DAY = "yyyy-MM-dd";
+
+ @Test
+ @AlfrescoTest (jira = "RM-5733,RM-5799")
+ public void checkRetentionAsOfDateForTransferStepWithRetentionAction() {
+
+ // create test precondition
+ createTestPrecondition(recordsCategory);
+
+ // create disposition schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
+
+ // add transfer step
+ HashMap transferStep = new HashMap<>();
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_PERIOD, "day|1");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.NAME, "transfer");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_PERIOD_PROPERTY, "rma:cutOffDate");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.COMBINE_DISPOSITION_STEP_CONDITIONS, "false");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_ELIGIBLE_FIRST_EVENT, "true");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.RETENTION_GHOST, "on");
+ transferStep.put(BaseAPI.RETENTION_SCHEDULE.DESCRIPTION, "Transfer after 1 day");
+ recordCategoriesAPI.addDispositionScheduleSteps(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), Category1.getName(), transferStep);
+
+ // create a folder and an electronic and a non-electronic record in it
+ RecordCategoryChild FOLDER = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ String nonElectronicRecord = TEST_PREFIX + "RM-5733 non-electronic record";
+ Record nonElRecord = createNonElectronicRecord(FOLDER.getId(), nonElectronicRecord);
+
+ // complete records and cut them off
+ String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
+
+ // complete records and cut them off
+ completeRecord(nonElRecord.getId());
+
+ String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
+
+ JSONObject nextDispositionActionJson = recordCategoriesAPI.getNextDispositionAction(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),nonElRecord.getId());
+
+ assertTrue(getAsOfDate(nextDispositionActionJson).startsWith(getTomorrow()),
+ "The retention as of date is not set to tomorrow.");
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void cleanUp() {
+ // delete category
+ deleteRecordCategory(Category1.getId());
+ }
+
+ private void createTestPrecondition(String categoryName) {
+ createRMSiteIfNotExists();
+
+ // create "rm admin" user if it does not exist and assign it to RM Administrator role
+ rmRolesAndActionsAPI.createUserAndAssignToRole(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
+
+ // create category
+ STEP("Create category");
+ Category1 = createRootCategory(categoryName,"Title");
+ }
+
+ private String getAsOfDate(JSONObject nextDispositionActionJson) {
+ return nextDispositionActionJson.getJSONObject("data").get("asOf").toString();
+ }
+
+ private static String getTomorrow() {
+ Date today = new Date();
+ Date tomorrow = DateUtils.addDays(today, 1);
+ SimpleDateFormat dateFormat = new SimpleDateFormat(YEAR_MONTH_DAY);
+ return dateFormat.format(tomorrow);
+ }
+
+}
\ No newline at end of file
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleTests.java
new file mode 100644
index 0000000000..90823b3514
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleTests.java
@@ -0,0 +1,202 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.core.v0.RMEvents;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.Test;
+import java.io.IOException;
+import java.time.Instant;
+import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
+import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.report.log.Step.STEP;
+
+/**
+ * Contains recordsDispositionScheduleWithoutGhosting test which checks disposition schedule cut off, transfer and destroy without maintaining metadata steps applied to records
+ *
+ * Precondition:
+ *
+ * RM site created, contains an empty category "RM-2801 disposition for records".
+ * RM user has RM admin role.
+ * A transfer location named "transferred files" is created to which RM user has access
+ *
+ *
+ *
+ * @author Kavit Shah
+ */
+
+public class RecordsDispositionScheduleTests extends BaseRMRestTest {
+
+ /** data prep 6services */
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ private RecordCategory Category1;
+ private final String TEST_PREFIX = generateTestPrefix(RecordsDispositionScheduleTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private final String recordsCategory = TEST_PREFIX + "RM-2801 category";
+ private final String folderDisposition = TEST_PREFIX + "RM-2801 folder";
+
+ @Test
+ @AlfrescoTest(jira="RM-2801")
+ public void recordsDispositionScheduleWithoutGhosting() {
+
+ // create test precondition
+ createTestPrecondition(recordsCategory);
+
+ // create disposition schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
+
+ // add transfer step
+ dispositionScheduleService.addTransferAfterEventStep(Category1.getName(),"transferred records","all_allowances_granted_are_terminated");
+
+ // add destroy step without retaining metadata
+ dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(Category1.getName(), "day|1", CUT_OFF_DATE);
+
+ // create a folder and an electronic and a non-electronic record in it
+ RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ String electronicRecord = "RM-2801 electronic record";
+ Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(), electronicRecord);
+ String nonElectronicRecord = "RM-2801 non-electronic record";
+ Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(), nonElectronicRecord);
+
+ // complete records and cut them off
+ String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
+ String elRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), folderDisposition, electronicRecord);
+
+ // complete records and cut them off
+ completeRecord(elRecord.getId());
+ completeRecord(nonElRecord.getId());
+
+ String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
+
+ String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
+
+ // ensure the complete event action is displayed for both events
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), nonElRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), elRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
+
+ // Create and Complete transfer
+ HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition));
+
+ String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
+
+ HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition));
+
+ String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
+
+ // edit the disposition schedule date to current date
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
+
+ Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
+
+ // destroy records
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
+
+ // delete category
+ deleteRecordCategory(Category1.getId());
+ }
+
+ private void createTestPrecondition(String categoryName) {
+ createRMSiteIfNotExists();
+
+ // create "rm admin" user if it does not exist and assign it to RM Administrator role
+ rmRolesAndActionsAPI.createUserAndAssignToRole(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
+
+ // create category
+ STEP("Create two category");
+ Category1 = createRootCategory(categoryName,"Title");
+ }
+
+ private String getTransferId(HttpResponse httpResponse,String nodeRef) {
+ HttpEntity entity = httpResponse.getEntity();
+ String responseString = null;
+ try {
+ responseString = EntityUtils.toString(entity, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ JSONObject result = new JSONObject(responseString);
+ return result
+ .getJSONObject("results")
+ .get(nodeRef)
+ .toString();
+
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleWithGhostingTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleWithGhostingTests.java
new file mode 100644
index 0000000000..07742a0767
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/RecordsDispositionScheduleWithGhostingTests.java
@@ -0,0 +1,200 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+
+package org.alfresco.rest.rm.community.smoke;
+
+import org.alfresco.rest.core.v0.RMEvents;
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.Record;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RecordFoldersAPI;
+import org.alfresco.rest.v0.RecordsAPI;
+import org.alfresco.rest.v0.service.DispositionScheduleService;
+import org.alfresco.test.AlfrescoTest;
+import org.alfresco.utility.Utility;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.Test;
+import java.io.IOException;
+import java.time.Instant;
+import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.report.log.Step.STEP;
+
+/**
+ * Contains recordsDispositionScheduleWithGhosting test which checks disposition schedule cut off, transfer and destroy with maintaining record metadata steps applied to records
+ *
+ * Precondition:
+ *
+ * RM site created, contains an empty category "RM-2937 disposition for records with ghosting".
+ * RM user has RM admin role.
+ * A transfer location named "transferred files with ghosting" is created to which RM user has access
+ *
+ *
+ *
+ * @author Kavit Shah
+ */
+public class RecordsDispositionScheduleWithGhostingTests extends BaseRMRestTest {
+
+ /** data prep 6services */
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ @Autowired
+ private RecordsAPI recordsAPI;
+ @Autowired
+ private RecordFoldersAPI recordFoldersAPI;
+ @Autowired
+ private DispositionScheduleService dispositionScheduleService;
+ private RecordCategory Category1;
+ private final String TEST_PREFIX = generateTestPrefix(RecordsDispositionScheduleTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private final String recordsCategory = TEST_PREFIX + "RM-2801 category";
+ private final String folderDisposition = TEST_PREFIX + "RM-2801 folder";
+
+ @Test
+ @AlfrescoTest(jira="RM-2801")
+ public void recordsDispositionScheduleWithGhosting() {
+
+ // create test precondition
+ createTestPrecondition(recordsCategory);
+
+ // create disposition schedule
+ dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
+
+ // add cut off step
+ dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
+
+ // add transfer step
+ dispositionScheduleService.addTransferAfterEventStep(Category1.getName(),"transferred records","all_allowances_granted_are_terminated");
+
+ // add destroy step without retaining metadata
+ dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
+
+ // create a folder and an electronic and a non-electronic record in it
+ RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
+
+ String electronicRecord = "RM-2801 electronic record";
+ Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(), electronicRecord);
+ String nonElectronicRecord = "RM-2801 non-electronic record";
+ Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(), nonElectronicRecord);
+
+ // complete records and cut them off
+ String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
+ String elRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), folderDisposition, electronicRecord);
+
+ // complete records and cut them off
+ completeRecord(elRecord.getId());
+ completeRecord(nonElRecord.getId());
+
+ String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
+
+ String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
+
+ // ensure the complete event action is displayed for both events
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), nonElRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
+ rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
+ getAdminUser().getPassword(), elRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
+
+ // Create and Complete transfer
+ HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition));
+
+ String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
+
+ HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition));
+
+ String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
+
+ // edit the disposition schedule date to current date
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
+
+ Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
+
+ // destroy records
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
+ recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
+ getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
+
+ // delete category
+ deleteRecordCategory(Category1.getId());
+ }
+
+ private void createTestPrecondition(String categoryName) {
+ createRMSiteIfNotExists();
+
+ // create "rm admin" user if it does not exist and assign it to RM Administrator role
+ rmRolesAndActionsAPI.createUserAndAssignToRole(
+ getDataUser().usingAdmin().getAdminUser().getUsername(),
+ getDataUser().usingAdmin().getAdminUser().getPassword(),
+ RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
+
+ // create category
+ STEP("Create two category");
+ Category1 = createRootCategory(categoryName,"Title");
+ }
+
+ private String getTransferId(HttpResponse httpResponse,String nodeRef) {
+ HttpEntity entity = httpResponse.getEntity();
+ String responseString = null;
+ try {
+ responseString = EntityUtils.toString(entity, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ JSONObject result = new JSONObject(responseString);
+ return result
+ .getJSONObject("results")
+ .get(nodeRef)
+ .toString();
+
+ }
+}
diff --git a/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/UnfiledRecordsRuleTests.java b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/UnfiledRecordsRuleTests.java
new file mode 100644
index 0000000000..a7023a1723
--- /dev/null
+++ b/amps/ags/rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/smoke/UnfiledRecordsRuleTests.java
@@ -0,0 +1,124 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2022 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * -
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ * -
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * -
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * -
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.smoke;
+
+
+import org.alfresco.rest.rm.community.base.BaseRMRestTest;
+import org.alfresco.rest.rm.community.model.record.RecordContent;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
+import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
+import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
+import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainer;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChild;
+import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildProperties;
+import org.alfresco.rest.v0.RMRolesAndActionsAPI;
+import org.alfresco.rest.v0.RulesAPI;
+import org.alfresco.test.AlfrescoTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
+import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME;
+import static org.alfresco.rest.rm.community.base.TestData.NONELECTRONIC_RECORD_NAME;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
+import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.*;
+import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
+import static org.alfresco.utility.data.RandomData.getRandomName;
+import static org.alfresco.utility.report.log.Step.STEP;
+import static org.springframework.http.HttpStatus.*;
+public class UnfiledRecordsRuleTests extends BaseRMRestTest {
+
+ @Autowired
+ private RMRolesAndActionsAPI rmRolesAndActionsAPI;
+ private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
+ private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
+ private RecordCategory Category2;
+ private RecordCategoryChild Folder2;
+ @Autowired
+ private RulesAPI rulesAPI;
+
+ @Test
+ @AlfrescoTest(jira = "RM-2794")
+ public void unfiledRecordsRule() {
+
+
+ STEP("Create the RM site if doesn't exist");
+ createRMSiteIfNotExists();
+
+ STEP("Create RM Admin user");
+ rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
+ getAdminUser().getPassword(),
+ "Administrator");
+
+ STEP("Create record categories and record folders");
+ Category2 = createRootCategory(getRandomName("recordCategory"));
+ Folder2 = createFolder(Category2.getId(), getRandomName("recordFolder"));
+
+ STEP("Get the unfiled records container");
+ UnfiledContainer container = getRestAPIFactory().getUnfiledContainersAPI().getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS);
+
+ // Check the response code
+ assertStatusCode(OK);
+
+ //create a rule
+ RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
+ .applyToChildren(true)
+ .actions(Collections.singletonList(ActionsOnRule.FILE_TO.getActionValue()));
+ rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + container.getId(), ruleDefinition);
+
+ //upload an electronic record
+ UnfiledContainerChild electronicRecord = UnfiledContainerChild.builder()
+ .name(ELECTRONIC_RECORD_NAME)
+ .nodeType(CONTENT_TYPE)
+ .content(RecordContent.builder().mimeType("text/plain").build())
+ .build();
+ assertStatusCode(OK);
+
+
+ // create a non-electronic record
+ UnfiledContainerChild nonelectronicRecord = UnfiledContainerChild.builder()
+ .properties(UnfiledContainerChildProperties.builder()
+ .description(NONELECTRONIC_RECORD_NAME)
+ .title("Title")
+ .build())
+ .name(NONELECTRONIC_RECORD_NAME)
+ .nodeType(NON_ELECTRONIC_RECORD_TYPE)
+ .build();
+ assertStatusCode(OK);
+
+ //delete the record created, delete the rule from UnfilledRecord page, delete the category created
+ rulesAPI.deleteAllRulesOnContainer(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + container.getId());
+ deleteRecordCategory(Category2.getId());
+ assertStatusCode(NO_CONTENT);
+
+ }
+
+ }
diff --git a/amps/ags/rm-community/pom.xml b/amps/ags/rm-community/pom.xml
index 4f8ff01d1d..25287472cf 100644
--- a/amps/ags/rm-community/pom.xml
+++ b/amps/ags/rm-community/pom.xml
@@ -7,7 +7,7 @@
org.alfrescoalfresco-governance-services-community-parent
- 17.43-SNAPSHOT
+ 20.5-SNAPSHOT
diff --git a/amps/ags/rm-community/rm-community-repo/.env b/amps/ags/rm-community/rm-community-repo/.env
index ca3c68b5dc..c6c00a9d5d 100644
--- a/amps/ags/rm-community/rm-community-repo/.env
+++ b/amps/ags/rm-community/rm-community-repo/.env
@@ -1,3 +1,3 @@
-SOLR6_TAG=2.0.3
-POSTGRES_TAG=13.3
-ACTIVEMQ_TAG=5.16.1
+SOLR6_TAG=2.0.5
+POSTGRES_TAG=14.4
+ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
diff --git a/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties b/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties
index a669cf8351..e6f4de0337 100644
--- a/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties
+++ b/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties
@@ -109,6 +109,10 @@ rm.completerecord.mandatorypropertiescheck.enabled=true
#
rm.patch.v22.convertToStandardFilePlan=false
+#
+# Max Batch size for adding the associations between the frozen nodes and the hold
+rm.patch.v35.holdNewChildAssocPatch.batchSize=1000
+
# Permission mapping
# these take a comma separated string of permissions from org.alfresco.service.cmr.security.PermissionService
# read maps to ReadRecords and write to FileRecords
diff --git a/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml b/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml
index 6159adab5f..c29851a583 100644
--- a/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml
+++ b/amps/ags/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml
@@ -17,5 +17,6 @@
+
diff --git a/amps/ags/rm-community/rm-community-repo/pom.xml b/amps/ags/rm-community/rm-community-repo/pom.xml
index 3e4f814212..477ddf77eb 100644
--- a/amps/ags/rm-community/rm-community-repo/pom.xml
+++ b/amps/ags/rm-community/rm-community-repo/pom.xml
@@ -8,7 +8,7 @@
org.alfrescoalfresco-governance-services-community-repo-parent
- 17.43-SNAPSHOT
+ 20.5-SNAPSHOT
@@ -434,7 +434,7 @@
- alfresco/alfresco-activemq:${dependency.activemq.version}
+ alfresco/alfresco-activemq:${dependency.activemq.version}-jre11-rockylinux8${activemq.port1}:${activemq.port1}
@@ -505,7 +505,7 @@
- alfresco/alfresco-activemq:${dependency.activemq.version}
+ alfresco/alfresco-activemq:${dependency.activemq.version}-jre11-rockylinux8${activemq.port1}:${activemq.port1}
diff --git a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
index 04def910c1..1603e32c9f 100644
--- a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
+++ b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
@@ -38,9 +38,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import lombok.extern.slf4j.Slf4j;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.ViewRecordsCapability;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
@@ -76,6 +79,7 @@ import org.json.simple.JSONObject;
*
* @author Roy Wetherall
*/
+@Slf4j
public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONConversionComponent
implements NodeServicePolicies.OnDeleteNodePolicy,
NodeServicePolicies.OnCreateNodePolicy
@@ -515,17 +519,25 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
AuthenticationUtil.runAsSystem((RunAsWork) () -> {
//Add details of the next incomplete event in the disposition schedule
- if (dispositionService.getNextDispositionAction(nodeRef) != null)
+ DispositionAction nextDispositionAction = dispositionService.getNextDispositionAction(nodeRef);
+ if (nextDispositionAction != null)
{
- for (EventCompletionDetails details : dispositionService.getNextDispositionAction(nodeRef).getEventCompletionDetails())
+ for (EventCompletionDetails details : nextDispositionAction.getEventCompletionDetails())
{
if (!details.isEventComplete())
{
+ DispositionActionDefinition dispositionActionDefinition = nextDispositionAction.getDispositionActionDefinition();
HashMap properties = (HashMap) rmNodeValues.get("properties");
- properties.put("combineDispositionStepConditions", nodeService.getProperty(dispositionService.getNextDispositionAction(nodeRef).getDispositionActionDefinition().getNodeRef(), PROP_COMBINE_DISPOSITION_STEP_CONDITIONS));
properties.put("incompleteDispositionEvent", details.getEventName());
- properties.put("dispositionEventCombination", nodeService.getProperty(dispositionService.getNextDispositionAction(nodeRef).getDispositionActionDefinition().getNodeRef(), PROP_DISPOSITION_EVENT_COMBINATION));
-
+ if(dispositionActionDefinition == null)
+ {
+ log.debug("Disposition action definition for disposition action "+ nextDispositionAction.getName() +" has been removed or never exist");
+ }
+ else
+ {
+ properties.put("combineDispositionStepConditions", nodeService.getProperty(dispositionActionDefinition.getNodeRef(), PROP_COMBINE_DISPOSITION_STEP_CONDITIONS));
+ properties.put("dispositionEventCombination", nodeService.getProperty(dispositionActionDefinition.getNodeRef(), PROP_DISPOSITION_EVENT_COMBINATION));
+ }
break;
}
}
diff --git a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java
index 12f2fc30a0..507f61cdc1 100644
--- a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java
+++ b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatch.java
@@ -30,6 +30,9 @@ import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel.RM_CUSTOM_URI;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASSOC_FROZEN_CONTENT;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import org.alfresco.model.ContentModel;
@@ -37,11 +40,14 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Patch to create new hold child association to link the record to the hold
@@ -52,8 +58,15 @@ import org.alfresco.service.namespace.RegexQNamePattern;
*/
public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
{
+ /** logger */
+ protected static final Logger LOGGER = LoggerFactory.getLogger(RMv35HoldNewChildAssocPatch.class);
+
/** A name for the associations created by this patch. */
- protected static final QName PATCH_ASSOC_NAME = QName.createQName(RM_CUSTOM_URI, RMv35HoldNewChildAssocPatch.class.getSimpleName());
+ protected static final QName PATCH_ASSOC_NAME = QName.createQName(RM_CUSTOM_URI,
+ RMv35HoldNewChildAssocPatch.class.getSimpleName());
+
+ /** The batch size for processing frozen nodes. */
+ private int batchSize = 1000;
/**
* File plan service interface
@@ -75,7 +88,8 @@ public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
/**
* Setter for fileplanservice
*
- * @param filePlanService File plan service interface
+ * @param filePlanService
+ * File plan service interface
*/
public void setFilePlanService(FilePlanService filePlanService)
{
@@ -85,7 +99,8 @@ public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
/**
* Setter for hold service
*
- * @param holdService Hold service interface.
+ * @param holdService
+ * Hold service interface.
*/
public void setHoldService(HoldService holdService)
{
@@ -95,7 +110,8 @@ public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
/**
* Setter for node service
*
- * @param nodeService Interface for public and internal node and store operations.
+ * @param nodeService
+ * Interface for public and internal node and store operations.
*/
public void setNodeService(NodeService nodeService)
{
@@ -112,33 +128,49 @@ public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
this.behaviourFilter = behaviourFilter;
}
+ /**
+ * Setter for maximum batch size
+ *
+ * @param maxBatchSize
+ * The max amount of associations to be created between the frozen nodes and the hold in a transaction
+ */
+ public void setBatchSize(int batchSize)
+ {
+ this.batchSize = batchSize;
+ }
+
@Override
public void applyInternal()
{
behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
behaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
+
try
{
+ int patchedNodesCounter = 0;
+
for (NodeRef filePlan : filePlanService.getFilePlans())
{
for (NodeRef hold : holdService.getHolds(filePlan))
{
- List frozenAssoc = nodeService.getChildAssocs(hold, ASSOC_FROZEN_CONTENT, RegexQNamePattern.MATCH_ALL);
- for (ChildAssociationRef ref : frozenAssoc)
+ LOGGER.debug("Analyzing hold {}", hold.getId());
+
+ BatchWorker batchWorker = new BatchWorker(hold);
+
+ LOGGER.debug("Hold has {} items to be analyzed", batchWorker.getWorkSize());
+
+ while (batchWorker.hasMoreResults())
{
- NodeRef childNodeRef = ref.getChildRef();
- // In testing we found that this was returning more than just "contains" associations.
- // Possibly this is due to the code in Node2ServiceImpl.getParentAssocs not using the second parameter.
- List parentAssocs = nodeService.getParentAssocs(childNodeRef, ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- boolean childContainedByHold =
- parentAssocs.stream().anyMatch(entry -> entry.getParentRef().equals(hold) && entry.getTypeQName().equals(ASSOC_CONTAINS));
- if (!childContainedByHold)
- {
- nodeService.addChild(hold, childNodeRef, ASSOC_CONTAINS, PATCH_ASSOC_NAME);
- }
+ processBatch(hold, batchWorker);
}
+
+ LOGGER.debug("Patched {} items in hold", batchWorker.getTotalPatchedNodes());
+
+ patchedNodesCounter += batchWorker.getTotalPatchedNodes();
}
}
+
+ LOGGER.debug("Patch applied to {} children across all holds", patchedNodesCounter);
}
finally
{
@@ -146,4 +178,92 @@ public class RMv35HoldNewChildAssocPatch extends AbstractModulePatch
behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
}
}
+
+ private void processBatch(NodeRef hold, BatchWorker batch)
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(() -> {
+
+ Collection childRefs = batch.getNextWork();
+
+ LOGGER.debug("Processing batch of {} children in hold", childRefs.size());
+
+ for (ChildAssociationRef child : childRefs)
+ {
+ NodeRef childNodeRef = child.getChildRef();
+
+ if (!isChildContainedByHold(hold, childNodeRef))
+ {
+ nodeService.addChild(hold, childNodeRef, ASSOC_CONTAINS, PATCH_ASSOC_NAME);
+ batch.countPatchedNode();
+ }
+ }
+
+ return null;
+ }, false, true);
+ }
+
+ private boolean isChildContainedByHold(NodeRef hold, NodeRef child)
+ {
+ // In testing we found that this was returning more than just "contains" associations.
+ // Possibly this is due to the code in Node2ServiceImpl.getParentAssocs not using the second
+ // parameter.
+ List parentAssocs = nodeService.getParentAssocs(child, ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ return parentAssocs.stream()
+ .anyMatch(entry -> entry.getParentRef().equals(hold) && entry.getTypeQName().equals(ASSOC_CONTAINS));
+ }
+
+ private class BatchWorker
+ {
+ NodeRef hold;
+ int totalPatchedNodes = 0;
+ int workSize;
+ Iterator iterator;
+
+ public BatchWorker(NodeRef hold)
+ {
+ this.hold = hold;
+ setupHold();
+ }
+
+ public boolean hasMoreResults()
+ {
+ return iterator == null ? true : iterator.hasNext();
+ }
+
+ public void countPatchedNode()
+ {
+ this.totalPatchedNodes += 1;
+ }
+
+ public int getTotalPatchedNodes()
+ {
+ return totalPatchedNodes;
+ }
+
+ public int getWorkSize()
+ {
+ return workSize;
+ }
+
+ public void setupHold()
+ {
+ // Get child assocs without preloading
+ List holdChildren = nodeService.getChildAssocs(hold, ASSOC_FROZEN_CONTENT,
+ RegexQNamePattern.MATCH_ALL, Integer.MAX_VALUE, false);
+ this.iterator = holdChildren.listIterator();
+ this.workSize = holdChildren.size();
+ }
+
+ public Collection getNextWork()
+ {
+ List frozenNodes = new ArrayList(batchSize);
+ while (iterator.hasNext() && frozenNodes.size() < batchSize)
+ {
+ frozenNodes.add(iterator.next());
+ }
+ return frozenNodes;
+ }
+
+ }
+
}
diff --git a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/repo/rule/ExtendedRuleServiceImpl.java b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/repo/rule/ExtendedRuleServiceImpl.java
index 1c2738abcb..0cb33b926c 100644
--- a/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/repo/rule/ExtendedRuleServiceImpl.java
+++ b/amps/ags/rm-community/rm-community-repo/source/java/org/alfresco/repo/rule/ExtendedRuleServiceImpl.java
@@ -156,25 +156,24 @@ public class ExtendedRuleServiceImpl extends RuleServiceImpl
* @see org.alfresco.repo.rule.RuleServiceImpl#saveRule(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.rule.Rule)
*/
@Override
- public void saveRule(final NodeRef nodeRef, final Rule rule)
+ public Rule saveRule(final NodeRef nodeRef, final Rule rule)
{
validateWormLockRuleAction(rule);
if (filePlanService.isFilePlanComponent(nodeRef))
{
- AuthenticationUtil.runAsSystem(new RunAsWork()
+ return AuthenticationUtil.runAsSystem(new RunAsWork()
{
@Override
- public Void doWork()
+ public Rule doWork()
{
- ExtendedRuleServiceImpl.super.saveRule(nodeRef, rule);
- return null;
+ return ExtendedRuleServiceImpl.super.saveRule(nodeRef, rule);
}
});
}
else
{
- super.saveRule(nodeRef, rule);
+ return super.saveRule(nodeRef, rule);
}
}
diff --git a/amps/ags/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/rule/FilePlanRuleInheritanceTest.java b/amps/ags/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/rule/FilePlanRuleInheritanceTest.java
index 4a09476861..5a0903be74 100644
--- a/amps/ags/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/rule/FilePlanRuleInheritanceTest.java
+++ b/amps/ags/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/rule/FilePlanRuleInheritanceTest.java
@@ -82,13 +82,7 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
public void given()
{
filePlan = createFilePlan();
-
- // create a rule that applies to childre
- Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
- rule = new Rule();
- rule.setRuleType("inbound");
- rule.setAction(completeRecordAction);
- rule.applyToChildren(true);
+ rule = createRuleThatAppliesToChildren();
}
public void when()
@@ -127,13 +121,7 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
public void given()
{
filePlan = createFilePlan();
-
- // create a rule that applies to childre
- Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
- rule = new Rule();
- rule.setRuleType("inbound");
- rule.setAction(completeRecordAction);
- rule.applyToChildren(true);
+ rule = createRuleThatAppliesToChildren();
}
public void when()
@@ -171,13 +159,7 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
public void given()
{
filePlan = createFilePlan();
-
- // create a rule that applies to childre
- Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
- rule = new Rule();
- rule.setRuleType("inbound");
- rule.setAction(completeRecordAction);
- rule.applyToChildren(true);
+ rule = createRuleThatAppliesToChildren();
}
public void when()
@@ -215,13 +197,7 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
public void given()
{
filePlan = createFilePlan();
-
- // create a rule that applies to childre
- Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
- rule = new Rule();
- rule.setRuleType("inbound");
- rule.setAction(completeRecordAction);
- rule.applyToChildren(true);
+ rule = createRuleThatAppliesToChildren();
}
public void when()
@@ -261,13 +237,7 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
{
filePlan = createFilePlan();
recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
-
- // create a rule that applies to childre
- Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
- rule = new Rule();
- rule.setRuleType("inbound");
- rule.setAction(completeRecordAction);
- rule.applyToChildren(true);
+ rule = createRuleThatAppliesToChildren();
}
public void when()
@@ -286,4 +256,15 @@ public class FilePlanRuleInheritanceTest extends BaseRMTestCase
}
});
}
+
+ private Rule createRuleThatAppliesToChildren()
+ {
+ Action completeRecordAction = actionService.createAction(DeclareRecordAction.NAME);
+ Rule rule = new Rule();
+ rule.setRuleType("inbound");
+ rule.setTitle("Rule name");
+ rule.setAction(completeRecordAction);
+ rule.applyToChildren(true);
+ return rule;
+ }
}
diff --git a/amps/ags/rm-community/rm-community-repo/test/resources/alfresco/version.properties b/amps/ags/rm-community/rm-community-repo/test/resources/alfresco/version.properties
index 63b9b4bb6d..ca959b89a7 100644
--- a/amps/ags/rm-community/rm-community-repo/test/resources/alfresco/version.properties
+++ b/amps/ags/rm-community/rm-community-repo/test/resources/alfresco/version.properties
@@ -4,7 +4,7 @@
# Version label
version.major=7
-version.minor=3
+version.minor=4
version.revision=0
version.label=
diff --git a/amps/ags/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java b/amps/ags/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java
index e799923b1c..4fabc47300 100644
--- a/amps/ags/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java
+++ b/amps/ags/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/patch/v35/RMv35HoldNewChildAssocPatchUnitTest.java
@@ -34,7 +34,9 @@ import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASSOC_FROZEN_CONTENT;
import static org.alfresco.module.org_alfresco_module_rm.patch.v35.RMv35HoldNewChildAssocPatch.PATCH_ASSOC_NAME;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyMap;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -51,16 +53,21 @@ import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.service.transaction.TransactionService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
/**
* RM V3.5 Create new hold child association to link the record to the hold
@@ -81,6 +88,12 @@ public class RMv35HoldNewChildAssocPatchUnitTest
@Mock
private BehaviourFilter mockBehaviourFilter;
+ @Mock
+ private TransactionService mockTransactionService;
+
+ @Mock
+ private RetryingTransactionHelper mockRetryingTransactionHelper;
+
@InjectMocks
private RMv35HoldNewChildAssocPatch patch;
@@ -112,25 +125,63 @@ public class RMv35HoldNewChildAssocPatchUnitTest
/**
* Test secondary associations are created for held items so that they are "contained" in the hold.
*/
+ @SuppressWarnings("unchecked")
@Test
public void testAddChildDuringUpgrade()
{
when(mockFilePlanService.getFilePlans()).thenReturn(fileplans);
when(mockHoldService.getHolds(filePlanRef)).thenReturn(holds);
- when(mockNodeService.getChildAssocs(holdRef, ASSOC_FROZEN_CONTENT, RegexQNamePattern.MATCH_ALL)).thenReturn(childAssocs);
+ when(mockNodeService.getChildAssocs(holdRef, ASSOC_FROZEN_CONTENT, RegexQNamePattern.MATCH_ALL, Integer.MAX_VALUE, false))
+ .thenReturn(childAssocs);
when(childAssociationRef.getChildRef()).thenReturn(heldItemRef);
+ // setup retrying transaction helper
+ Answer