mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	Compare commits
	
		
			78 Commits
		
	
	
		
			25.2.0.27
			...
			fix/MNT-24
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 36bc1dc1a4 | ||
|  | 8407159a17 | ||
|  | 917dd35c27 | ||
|  | 6e815ebd34 | ||
|  | ad0668cce3 | ||
|  | 11fd7ca1dd | ||
|  | 6be0c3031f | ||
|  | a1d869bdef | ||
|  | d130c12f2a | ||
|  | 24e987e735 | ||
|  | 63e7492823 | ||
|  | 545a957a1b | ||
|  | 325e980cf0 | ||
|  | e2a4dcc6ad | ||
|  | a993c9ed97 | ||
|  | 85d2a5176b | ||
|  | 3c245ae64c | ||
|  | fbf5966d10 | ||
|  | 8fca14df40 | ||
|  | e38e7b4bda | ||
|  | b378de58d8 | ||
|  | 8a64d9fb0b | ||
|  | 3c092b696d | ||
|  | 6f222106c5 | ||
|  | bd5a016382 | ||
|  | dc24718717 | ||
|  | e65614d3c2 | ||
|  | 698f9b15ce | ||
|  | 09a254e5fd | ||
|  | 6f442a703a | ||
|  | f1862c9636 | ||
|  | 231075fd5e | ||
|  | 979420879c | ||
|  | db330e28f5 | ||
|  | bae0573636 | ||
|  | 8089fc2572 | ||
|  | 1c4fe53c0f | ||
|  | 7a8aa1a2c1 | ||
|  | e08ba1fd4f | ||
|  | 4f40bd0687 | ||
|  | a3578f7baa | ||
|  | 8e8b9c868f | ||
|  | f77b3b79e5 | ||
|  | 3a7157f4a7 | ||
|  | d6b979f341 | ||
|  | a090de4e71 | ||
|  | 03621db30a | ||
|  | 766a6def2b | ||
|  | 117804fb68 | ||
|  | f03e6761ce | ||
|  | 74c8288206 | ||
|  | c0bd0a680b | ||
|  | 8645cdc76d | ||
|  | 5055eec2df | ||
|  | 892f41d6fd | ||
|  | 075b02baee | ||
|  | 7c8a75ce6c | ||
|  | cb0a925e27 | ||
|  | c7d2699f7e | ||
|  | b942b55193 | ||
|  | c1100fe983 | ||
|  | 62236c90f5 | ||
|  | eabdab91fb | ||
|  | 4f83076cfe | ||
|  | 7eda1d420f | ||
|  | 411388d62d | ||
|  | 245d1317ac | ||
|  | ee5e34ca32 | ||
|  | c4dcef73e1 | ||
|  | 4f53fee1fc | ||
|  | d163410e3d | ||
|  | 9ca251edba | ||
|  | 193cb9b30d | ||
|  | e9a36f67fe | ||
|  | c18a58caea | ||
|  | 11659ab917 | ||
|  | b8fc8efa07 | ||
|  | 2e851cf88d | 
							
								
								
									
										629
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										629
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -29,9 +29,6 @@ env: | ||||
|   AUTH0_CLIENT_ID: ${{ secrets.AUTH0_OIDC_ADMIN_CLIENT_ID }} | ||||
|   AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_OIDC_CLIENT_SECRET }} | ||||
|   AUTH0_ADMIN_PASSWORD: ${{ secrets.AUTH0_OIDC_ADMIN_PASSWORD }} | ||||
|   # Report Portal settings | ||||
|   RP_LAUNCH_PREFIX: "${{ github.workflow }} - ${{ github.job }}" | ||||
|   RP_PROJECT: alfresco-backend | ||||
|  | ||||
| jobs: | ||||
|   prepare: | ||||
| @@ -182,52 +179,9 @@ jobs: | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.16.0 | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testModule }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl ${{ matrix.testModule }} -am ${{ matrix.testAttributes }} -DfailIfNoTests=false "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -270,52 +224,8 @@ jobs: | ||||
|       - name: "Set up the environment" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl remote-api -Dtest=${{ matrix.testSuite }} -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|             echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: mvn -B test -pl remote-api -Dtest=${{ matrix.testSuite }} -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco  # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -345,52 +255,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile mariadb up -d | ||||
|         env: | ||||
|           MARIADB_VERSION: ${{ matrix.version }} | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.version }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -416,52 +282,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile mariadb up -d | ||||
|         env: | ||||
|           MARIADB_VERSION: 10.11 | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -487,52 +309,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile mysql up -d | ||||
|         env: | ||||
|           MYSQL_VERSION: 8 | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl repository -am -Dtest=AllDBTestsTestSuite -DfailIfNoTests=false -Ddb.driver=com.mysql.cj.jdbc.Driver -Ddb.name=alfresco -Ddb.url=jdbc:mysql://localhost:3307/alfresco -Ddb.username=alfresco -Ddb.password=alfresco "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -557,52 +335,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile postgres up -d | ||||
|         env: | ||||
|           POSTGRES_VERSION: 14.15 | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -627,52 +361,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile postgres up -d | ||||
|         env: | ||||
|           POSTGRES_VERSION: 15.10 | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -697,52 +387,8 @@ jobs: | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose-db.yaml --profile postgres up -d | ||||
|         env: | ||||
|           POSTGRES_VERSION: 16.6 | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -763,52 +409,8 @@ jobs: | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run ActiveMQ" | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile activemq up -d | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl repository -am -Dtest=MessagingUnitTestSuite -DfailIfNoTests=false "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: mvn -B test -pl repository -am -Dtest=CamelRoutesTest,CamelComponentsTest -DfailIfNoTests=false # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -879,52 +481,8 @@ jobs: | ||||
|       - name: "Set up the environment" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile ${{ matrix.compose-profile }} up -d | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.testSuite }} ${{ matrix.idp }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl repository -am -Dtest=${{ matrix.testSuite }} -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco ${{ matrix.mvn-options }} "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: mvn -B test -pl repository -am -Dtest=${{ matrix.testSuite }} -DfailIfNoTests=false -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco ${{ matrix.mvn-options }} # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -986,59 +544,16 @@ jobs: | ||||
|       - name: "Build TAS integration tests" | ||||
|         if: ${{ matrix.test-name }} == 'Integration TAS tests' | ||||
|         run: mvn install -pl :alfresco-community-repo-integration-test -am -DskipTests -Pall-tas-tests | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} - ${{ matrix.test-name }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B verify -f packaging/tests/${{ matrix.pom-dir }}/pom.xml -Pall-tas-tests,${{ matrix.test-profile }} -Denvironment=default -DrunBugs=false "${args[@]}" | ||||
|         continue-on-error: true | ||||
|         run: mvn -B verify -f packaging/tests/${{ matrix.pom-dir }}/pom.xml -Pall-tas-tests,${{ matrix.test-profile }} -Denvironment=default -DrunBugs=false | ||||
|       - name: "Print output after success" | ||||
|         if: ${{ always() && steps.tests.outcome == 'success' }} | ||||
|         run: ${TAS_SCRIPTS}/output_tests_run.sh "packaging/tests/${{ matrix.pom-dir }}" | ||||
|       - name: "Print output after failure" | ||||
|         if: ${{ always() && steps.tests.outcome == 'failure' }} | ||||
|         run: ${TAS_SCRIPTS}/output_logs_for_failures.sh "packaging/tests/${{ matrix.pom-dir }}" | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -1059,52 +574,8 @@ jobs: | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run Postgres 16.6 database" | ||||
|         run: docker compose -f ./scripts/ci/docker-compose/docker-compose.yaml --profile postgres up -d | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Run tests" | ||||
|         id: run-tests | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           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 "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: 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 # pragma: allowlist secret | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -1134,23 +605,9 @@ jobs: | ||||
|         run: | | ||||
|           bash ./scripts/ci/init.sh | ||||
|           bash ./scripts/ci/build.sh | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (PostgreSQL) ${{ matrix.test-name }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Verify" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-postgres -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} "${args[@]}" | ||||
|         run: mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-postgres -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -1180,23 +637,9 @@ jobs: | ||||
|         run: | | ||||
|           bash ./scripts/ci/init.sh | ||||
|           bash ./scripts/ci/build.sh | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} 0${{ matrix.part }} - (MySQL) ${{ matrix.test-name }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Verify" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-mysql -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} "${args[@]}" | ||||
|         run: mvn --file amps/ags/pom.xml -B verify -Dmaven.javadoc.skip=true -Dmaven.source.skip=true -Pags -Pstart-mysql -PagsAllTestSuitePt${{ matrix.part }} ${{ env.LOG_WARN }} | ||||
|       - name: "Clean Maven cache" | ||||
|         run: bash ./scripts/ci/cleanup_cache.sh | ||||
|  | ||||
| @@ -1228,53 +671,9 @@ jobs: | ||||
|           ${{ env.TAS_SCRIPTS }}/start-compose.sh ./amps/ags/rm-community/rm-community-repo/docker-compose.yml | ||||
|           ${{ env.TAS_SCRIPTS }}/wait-for-alfresco-start.sh "http://localhost:8080/alfresco" | ||||
|           mvn -B install -pl :alfresco-governance-services-automation-community-rest-api -am -Pags -Pall-tas-tests -DskipTests | ||||
|       - name: "Prepare Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-prepare@v8.16.0 | ||||
|         id: rp-prepare | ||||
|         with: | ||||
|           rp-launch-prefix: ${{ env.RP_LAUNCH_PREFIX }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-use-static-launch-name: true | ||||
|         continue-on-error: true | ||||
|       - name: "Add GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         env: | ||||
|           RP_ENABLED: ${{ steps.rp-prepare.outputs.enabled }} | ||||
|           RP_KEY: ${{ steps.rp-prepare.outputs.key }} | ||||
|           RP_URL: ${{ steps.rp-prepare.outputs.url }} | ||||
|         run: bash scripts/ci/add_step_summary.sh | ||||
|         continue-on-error: true | ||||
|       - name: "Test" | ||||
|         id: run-tests | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         env: | ||||
|           RP_OPTS: ${{ github.ref_name == 'master' && steps.rp-prepare.outputs.mvn-opts || '' }} | ||||
|         run: | | ||||
|           eval "args=($RP_OPTS)" | ||||
|           mvn -B test -pl :alfresco-governance-services-automation-community-rest-api -Dskip.automationtests=false -Pags -Pall-tas-tests "${args[@]}" | ||||
|         continue-on-error: true | ||||
|       - name: "Update GitHub Step Summary" | ||||
|         if: github.ref_name == 'master' | ||||
|         run: | | ||||
|           echo "#### ⏱ After Tests: $(date -u +'%Y-%m-%d %H:%M:%S%:z')" >> $GITHUB_STEP_SUMMARY | ||||
|         continue-on-error: true | ||||
|       - name: "Summarize Report Portal" | ||||
|         if: github.ref_name == 'master' | ||||
|         uses: Alfresco/alfresco-build-tools/.github/actions/reportportal-summarize@v8.16.0 | ||||
|         id: rp-summarize | ||||
|         with: | ||||
|           tests-outcome: ${{ steps.run-tests.outcome }} | ||||
|           rp-launch-key: ${{ steps.rp-prepare.outputs.key }} | ||||
|           rp-project: ${{ env.RP_PROJECT }} | ||||
|           rp-token: ${{ secrets.REPORT_PORTAL_TOKEN }} | ||||
|         continue-on-error: true | ||||
|       - name: "Exit on failure" | ||||
|         if: steps.run-tests.outcome != 'success' | ||||
|         run: | | ||||
|           echo "::error title=run-tests::Tests failed: re-throwing on error." | ||||
|           exit 1 | ||||
|         run: mvn -B test -pl :alfresco-governance-services-automation-community-rest-api -Dskip.automationtests=false -Pags -Pall-tas-tests | ||||
|       - name: "Configure AWS credentials" | ||||
|         if: ${{ always() }} | ||||
|         uses: aws-actions/configure-aws-credentials@v4 | ||||
|   | ||||
| @@ -127,29 +127,6 @@ | ||||
|     } | ||||
|   ], | ||||
|   "results": { | ||||
|     ".github/workflows/ci.yml": [ | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "b86dc2f033a63f2b7b9e7d270ab806d2910d7572", | ||||
|         "is_verified": false, | ||||
|         "line_number": 295 | ||||
|       }, | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "1bfb0e20f886150ba59b853bcd49dea893e00966", | ||||
|         "is_verified": false, | ||||
|         "line_number": 370 | ||||
|       }, | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "128f14373ccfaff49e3664045d3a11b50cbb7b39", | ||||
|         "is_verified": false, | ||||
|         "line_number": 904 | ||||
|       } | ||||
|     ], | ||||
|     ".github/workflows/master_release.yml": [ | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
| @@ -1273,7 +1250,7 @@ | ||||
|         "filename": "repository/src/main/resources/alfresco/repository.properties", | ||||
|         "hashed_secret": "84551ae5442affc9f1a2d3b4c86ae8b24860149d", | ||||
|         "is_verified": false, | ||||
|         "line_number": 770, | ||||
|         "line_number": 771, | ||||
|         "is_secret": false | ||||
|       } | ||||
|     ], | ||||
| @@ -1868,5 +1845,5 @@ | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "generated_at": "2025-03-27T23:45:41Z" | ||||
|   "generated_at": "2025-06-09T16:43:14Z" | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-automation-community-repo</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <build> | ||||
| @@ -74,16 +74,6 @@ | ||||
|          <artifactId>alfresco-testng</artifactId> | ||||
|          <version>1.1</version> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.squareup.okhttp3</groupId> | ||||
|          <artifactId>okhttp</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.awaitility</groupId> | ||||
|          <artifactId>awaitility</artifactId> | ||||
|   | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model; | ||||
|  | ||||
| public record CapabilityModel(String name, String title, String description, GroupModel group, int index) | ||||
| {} | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model; | ||||
|  | ||||
| public record GroupModel(String id, String title) | ||||
| {} | ||||
| @@ -0,0 +1,91 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import org.alfresco.rest.rm.community.model.CapabilityModel; | ||||
| import org.alfresco.utility.model.TestModel; | ||||
|  | ||||
| /** | ||||
|  * POJO for role | ||||
|  */ | ||||
| @Builder | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class Role extends TestModel | ||||
| { | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String name; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private List<CapabilityModel> capabilities; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String displayLabel; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String groupShortName; | ||||
|  | ||||
|     private List<String> assignedUsers; | ||||
|  | ||||
|     private List<String> assignedGroups; | ||||
|  | ||||
|     private String roleGroupName; | ||||
|  | ||||
|     @Override | ||||
|     public boolean equals(Object o) | ||||
|     { | ||||
|         if (this == o) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         if (o == null || getClass() != o.getClass()) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         Role role = (Role) o; | ||||
|         return Objects.equals(name, role.name) && Objects.equals(capabilities, role.capabilities) | ||||
|                 && Objects.equals(displayLabel, role.displayLabel) && Objects.equals(groupShortName, role.groupShortName) && Objects.equals(assignedUsers, role.assignedUsers) | ||||
|                 && Objects.equals(assignedGroups, role.assignedGroups) && Objects.equals(roleGroupName, role.roleGroupName); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int hashCode() | ||||
|     { | ||||
|         return Objects.hash(name, capabilities, displayLabel, groupShortName, assignedUsers, assignedGroups, roleGroupName); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import org.alfresco.rest.core.RestModels; | ||||
|  | ||||
| public class RoleCollection extends RestModels<RoleEntry, RoleCollection> | ||||
| {} | ||||
| @@ -0,0 +1,47 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import org.alfresco.rest.core.RestModels; | ||||
|  | ||||
| @Builder | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class RoleEntry extends RestModels<Role, RoleEntry> | ||||
| { | ||||
|     @JsonProperty | ||||
|     private Role entry; | ||||
| } | ||||
| @@ -35,7 +35,7 @@ package org.alfresco.rest.rm.community.model.user; | ||||
|  */ | ||||
| public enum UserRoles | ||||
| { | ||||
|     IN_PLACE_WRITERS("ExtendedWriters", "In-Place Writers"), ROLE_RM_ADMIN("Administrator", "Records Management Administrator"), ROLE_RM_MANAGER("RecordsManager", "Records Management Manager"), ROLE_RM_POWER_USER("PowerUser", "Records Management Power User"), ROLE_RM_SECURITY_OFFICER("SecurityOfficer", "Records Management Security Officer"), ROLE_RM_USER("User", "Records Management User"); | ||||
|     IN_PLACE_WRITERS("ExtendedWriters", "In-Place Writers"), ROLE_RM_ADMIN("Administrator", "Records Management Administrator"), ROLE_RM_MANAGER("RecordsManager", "Records Management Manager"), ROLE_RM_POWER_USER("PowerUser", "Records Management Power User"), ROLE_RM_SECURITY_OFFICER("SecurityOfficer", "Records Management Security Officer"), ROLE_RM_USER("User", "Records Management User"), IN_PLACE_READERS("ExtendedReaders", "In-Place Readers"); | ||||
|  | ||||
|     public final String roleId; | ||||
|     public final String displayName; | ||||
|   | ||||
| @@ -43,6 +43,7 @@ import org.alfresco.rest.rm.community.model.hold.Hold; | ||||
| import org.alfresco.rest.rm.community.model.hold.HoldCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection; | ||||
| import org.alfresco.rest.rm.community.model.role.RoleCollection; | ||||
| import org.alfresco.rest.rm.community.requests.RMModelRequest; | ||||
|  | ||||
| /** | ||||
| @@ -303,4 +304,39 @@ public class FilePlanAPI extends RMModelRequest | ||||
|     { | ||||
|         return getHolds(filePlanId, EMPTY); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the roles of a file plan. | ||||
|      * | ||||
|      * @param filePlanId | ||||
|      *            The identifier of a file plan | ||||
|      * @param parameters | ||||
|      *            The URL parameters to add | ||||
|      * @return The {Pagination and RoleModel Entries} for the given {@code filePlanId} | ||||
|      * @throws RuntimeException | ||||
|      *             for the following cases: | ||||
|      *             <ul> | ||||
|      *             <li>authentication fails</li> | ||||
|      *             <li>current user does not have permission to read {@code filePlanId}</li> | ||||
|      *             <li>{@code filePlanId} does not exist</li> | ||||
|      *             </ul> | ||||
|      */ | ||||
|     public RoleCollection getFilePlanRoles(String filePlanId, String parameters) | ||||
|     { | ||||
|         mandatoryString("filePlanId", filePlanId); | ||||
|         return getRmRestWrapper().processModels(RoleCollection.class, simpleRequest( | ||||
|                 GET, | ||||
|                 "file-plans/{filePlanId}/roles?{parameters}", | ||||
|                 filePlanId, | ||||
|                 parameters)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * See {@link #getFilePlanRoles(String, String)} | ||||
|      */ | ||||
|     public RoleCollection getFilePlanRoles(String filePlanId) | ||||
|     { | ||||
|         return getFilePlanRoles(filePlanId, EMPTY); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -93,6 +93,7 @@ import org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI; | ||||
| import org.alfresco.rest.search.RestRequestQueryModel; | ||||
| import org.alfresco.rest.search.SearchNodeModel; | ||||
| import org.alfresco.rest.search.SearchRequest; | ||||
| import org.alfresco.rest.v0.RMRolesAndActionsAPI; | ||||
| import org.alfresco.rest.v0.SearchAPI; | ||||
| import org.alfresco.utility.Utility; | ||||
| import org.alfresco.utility.data.DataUserAIS; | ||||
| @@ -127,6 +128,10 @@ public class BaseRMRestTest extends RestTest | ||||
|     @Getter(value = PROTECTED) | ||||
|     private SearchAPI searchApi; | ||||
|  | ||||
|     @Autowired | ||||
|     @Getter(PROTECTED) | ||||
|     private RMRolesAndActionsAPI rmRolesAndActionsV0API; | ||||
|  | ||||
|     protected static final String iso8601_DateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -28,6 +28,7 @@ package org.alfresco.rest.rm.community.fileplans; | ||||
|  | ||||
| import static java.util.Arrays.asList; | ||||
|  | ||||
| import static com.google.common.collect.Sets.newHashSet; | ||||
| import static org.springframework.http.HttpStatus.CONFLICT; | ||||
| import static org.springframework.http.HttpStatus.CREATED; | ||||
| import static org.springframework.http.HttpStatus.FORBIDDEN; | ||||
| @@ -56,19 +57,27 @@ import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanCo | ||||
| import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_CONTAINER_TYPE; | ||||
| import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.IN_PLACE_READERS; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.IN_PLACE_WRITERS; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_ADMIN; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_MANAGER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_POWER_USER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_SECURITY_OFFICER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_USER; | ||||
| import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric; | ||||
| import static org.alfresco.utility.data.RandomData.getRandomName; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.NoSuchElementException; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.testng.annotations.DataProvider; | ||||
| import org.testng.annotations.Test; | ||||
|  | ||||
| import org.alfresco.rest.rm.community.base.BaseRMRestTest; | ||||
| import org.alfresco.rest.rm.community.base.DataProviderClass; | ||||
| import org.alfresco.rest.rm.community.model.CapabilityModel; | ||||
| import org.alfresco.rest.rm.community.model.fileplan.FilePlan; | ||||
| import org.alfresco.rest.rm.community.model.fileplan.FilePlanProperties; | ||||
| import org.alfresco.rest.rm.community.model.hold.Hold; | ||||
| @@ -76,6 +85,9 @@ import org.alfresco.rest.rm.community.model.hold.HoldCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryProperties; | ||||
| import org.alfresco.rest.rm.community.model.role.Role; | ||||
| import org.alfresco.rest.rm.community.model.role.RoleCollection; | ||||
| import org.alfresco.rest.rm.community.model.user.UserCapabilities; | ||||
| import org.alfresco.rest.rm.community.requests.gscore.api.RMSiteAPI; | ||||
| import org.alfresco.utility.constants.ContainerName; | ||||
| import org.alfresco.utility.model.UserModel; | ||||
| @@ -87,6 +99,7 @@ import org.alfresco.utility.report.Bug; | ||||
|  * @author Rodica Sutu | ||||
|  * @since 2.6 | ||||
|  */ | ||||
| @SuppressWarnings("PMD.UnitTestShouldIncludeAssert") | ||||
| public class FilePlanTests extends BaseRMRestTest | ||||
| { | ||||
|     // ** Number of children (for children creation test) */ | ||||
| @@ -266,7 +279,7 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|      * When I ask the API to create a root record category | ||||
|      * Then it is created as a root record category | ||||
|      * </pre> | ||||
|      *  | ||||
|      * | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When I use the API to create a folder (cm:folder type) into the fileplan | ||||
| @@ -314,7 +327,7 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|      * When I ask the API to create a root category having the same name | ||||
|      * Then  the response code received is 409 - name clashes with an existing node | ||||
|      * </pre> | ||||
|      *  | ||||
|      * | ||||
|      * <pre> | ||||
|      * Given a root category | ||||
|      * When I ask the API to create a root category having the same name  with autoRename parameter on true | ||||
| @@ -594,4 +607,171 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When rmAdmin user ask the API for roles | ||||
|      * It provides list of all default roles | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void listFilePlanAllDefaultRoles() | ||||
|     { | ||||
|         List<String> defaultRolesDisplayNames = asList(IN_PLACE_READERS.displayName, ROLE_RM_ADMIN.displayName, ROLE_RM_MANAGER.displayName, ROLE_RM_POWER_USER.displayName, ROLE_RM_USER.displayName, IN_PLACE_WRITERS.displayName, ROLE_RM_SECURITY_OFFICER.displayName); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS); | ||||
|         assertStatusCode(OK); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertTrue(defaultRolesDisplayNames.contains(role.getDisplayLabel())); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When rmAdmin user ask the API for roles with SystemRoles as false | ||||
|      * It provides list of all roles excluding SystemRoles | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void listFilePlanAllRolesExcludeSystemRoles() | ||||
|     { | ||||
|         String parameters = "where=(systemRoles=false)"; | ||||
|         List<String> systemRolesDisplayNames = asList(IN_PLACE_WRITERS.displayName, IN_PLACE_READERS.displayName); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertFalse(systemRolesDisplayNames.contains(role.getDisplayLabel())); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a non-RM user asks the API for the roles | ||||
|      * Then the status code 403 (Permission denied) is return | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void nonRmUserFilePlanRoles() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel nonRMuser = getDataUser().createRandomTestUser("testUser"); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         getRestAPIFactory().getFilePlansAPI(nonRMuser).getFilePlanRoles(FILE_PLAN_ALIAS); | ||||
|         assertStatusCode(FORBIDDEN); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a RM_Manager user asks the API for the roles | ||||
|      * returns the RM_Manager role and capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void rmManagerFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel managerUser = getDataUser().createRandomTestUser("managerUser"); | ||||
|         // Assign RecordsManager role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(managerUser.getUsername(), ROLE_RM_MANAGER.roleId); | ||||
|         String parameters = "where=(personId='" + managerUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(managerUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertEquals(ROLE_RM_MANAGER.displayName, role.getDisplayLabel()); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a User with more than one role asks the API for the roles and relation | ||||
|      * returns the roles and capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void multipleRoleUserFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel rmUser = getDataUser().createRandomTestUser("rmUser"); | ||||
|         // Assign rmUser role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmUser.getUsername(), ROLE_RM_USER.roleId); | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmUser.getUsername(), ROLE_RM_POWER_USER.roleId); | ||||
|         String parameters = "where=(personId='" + rmUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(rmUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 2); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertTrue(role.getDisplayLabel().equals(ROLE_RM_USER.displayName) || role.getDisplayLabel().equals(ROLE_RM_POWER_USER.displayName)); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a new user with a new role asks the API for the roles and relation | ||||
|      * returns the new role and new capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void newRoleUserFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         /** A list of capabilities. */ | ||||
|         Set<String> newCapabilities = newHashSet(UserCapabilities.VIEW_RECORDS_CAP, UserCapabilities.DECLARE_RECORDS_CAP); | ||||
|         // Create a new role using old API | ||||
|         getRmRolesAndActionsV0API().createRole(getAdminUser().getUsername(), getAdminUser().getPassword(), "NewTestRole", | ||||
|                 "New Role Label", newCapabilities); | ||||
|         // Create a random user | ||||
|         UserModel rmNewUser = getDataUser().createRandomTestUser("rmPowerUser"); | ||||
|         // Assign New role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmNewUser.getUsername(), "NewTestRole"); | ||||
|         String parameters = "where=(personId='" + rmNewUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(rmNewUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 1); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             List<CapabilityModel> capabilities = roleModelEntry.getEntry().getCapabilities(); | ||||
|             capabilities.forEach(capabilityModel -> { | ||||
|                 assertTrue(newCapabilities.contains(capabilityModel.name())); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When API call happens with Capability filter | ||||
|      * returns roles associated with the capability | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void filePlanRolesAndCapabilitiesFilter() | ||||
|     { | ||||
|         String parameters = "where=(systemRoles=true and capabilityName in ('ManageRules'))"; | ||||
|         // Call to new API to get the roles and capabilities, filter by capability, include assigned users | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 1); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertEquals(ROLE_RM_ADMIN.displayName, role.getDisplayLabel()); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -139,7 +139,8 @@ public class AddToHoldsBulkV1Tests extends BaseRMRestTest | ||||
|         ancestorSearchRequest.setQuery(ancestorReq); | ||||
|  | ||||
|         STEP("Wait until paths are indexed."); | ||||
|         await().atMost(30, TimeUnit.SECONDS) | ||||
|         // to improve stability on CI - seems that sometimes during big load we need to wait longer for the condition | ||||
|         await().atMost(120, TimeUnit.SECONDS) | ||||
|                 .until(() -> getRestAPIFactory().getSearchAPI(null).search(ancestorSearchRequest).getPagination() | ||||
|                         .getTotalItems() == NUMBER_OF_FILES); | ||||
|  | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -23,7 +23,7 @@ Recorded content can be explicitly destroyed whilst maintaining the original nod | ||||
| * License: Alfresco Community | ||||
| * Issue Tracker Link: [JIRA RM](https://issues.alfresco.com/jira/projects/RM/summary) | ||||
| * Contribution Model: Alfresco Closed Source | ||||
| * Documentation: [docs.alfresco.com (Records Management)](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services-Community-Edition/23.4/Alfresco-Governance-Services-Community-Edition/Introduction) | ||||
| * Documentation: [docs.alfresco.com (Records Management)](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1&component=Alfresco%20Governance%20Services%20Community%20Edition) | ||||
|  | ||||
| ***  | ||||
|  | ||||
|   | ||||
| @@ -21,18 +21,18 @@ RM is split into two main parts - a repository integration and a Share integrati | ||||
| * [Community License](../LICENSE.txt) | ||||
| * [Enterprise License](../../rm-enterprise/LICENSE.txt) (this file will only be present in clones of the Enterprise repository) | ||||
| * [Issue Tracker Link](https://issues.alfresco.com/jira/projects/RM) | ||||
| * [Community Documentation Link](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services-Community-Edition/23.4/Alfresco-Governance-Services-Community-Edition/Introduction) | ||||
| * [Enterprise Documentation Link](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services/23.4/Alfresco-Governance-Services/Introduction) | ||||
| * [Community Documentation Link](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1&component=Alfresco%20Governance%20Services%20Community%20Edition) | ||||
| * [Enterprise Documentation Link](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1) | ||||
| * [Contribution Model](../../CONTRIBUTING.md) | ||||
|  | ||||
| ***  | ||||
|  | ||||
| ### Prerequisite Knowledge | ||||
| An understanding of Alfresco Content Services is assumed. The following pages from the [developer documentation](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services-Community-Edition/23.4/Alfresco-Content-Services-Community-Edition/Develop) give useful background information: | ||||
| An understanding of Alfresco Content Services is assumed. The following pages from the [developer documentation](https://support.hyland.com/access?dita:id=lsl1724405261585&vrm_version=25.2&component=Alfresco%20Content%20Services%20Community%20Edition) give useful background information: | ||||
|  | ||||
| * [ACS Architecture](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Software-Architecture) | ||||
| * [Platform Extensions](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Extension-Points-Overview) | ||||
| * [Share Extensions](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Share-UI-Extension-Points) | ||||
| * [ACS Architecture](https://support.hyland.com/access?dita:id=lfo1719554691023&vrm_version=25.2) | ||||
| * [Platform Extensions](https://support.hyland.com/access?dita:id=ifr1720080387005&vrm_version=25.2) | ||||
| * [Share Extensions](https://support.hyland.com/access?dita:id=wqu1720687386891&vrm_version=25.2) | ||||
|  | ||||
| ***  | ||||
|  | ||||
| @@ -44,12 +44,12 @@ The RM Share module communicates with the repository module via REST APIs. Inter | ||||
| * A DAO layer responsible for CRUD operations against the database. | ||||
|  | ||||
| #### REST API | ||||
| The REST API endpoints fall into two main types - v0 (Webscripts) and v1. The [v0 API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Web-Scripts) is older and not recommended for integrations. The [v1 API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/REST-API-Guide) is newer but isn't yet feature complete. If you are running RM locally then the GS API Explorer will be available at [this link](http://localhost:8080/gs-api-explorer/). | ||||
| The REST API endpoints fall into two main types - v0 (Webscripts) and v1. The [v0 API](https://support.hyland.com/access?dita:id=fga1720080409048&vrm_version=25.2) is older and not recommended for integrations. The [v1 API](https://support.hyland.com/access?dita:id=cmm1721136574006&vrm_version=25.2) is newer but isn't yet feature complete. If you are running RM locally then the GS API Explorer will be available at [this link](http://localhost:8080/gs-api-explorer/). | ||||
|  | ||||
| Internally the GS v1 REST API is built on the [Alfresco v1 REST API framework](https://community.alfresco.com/community/ecm/blog/2016/10/11/v1-rest-api-part-1-introduction). It aims to be consistent with this in terms of behaviour and naming. | ||||
|  | ||||
| #### Java Public API | ||||
| The Java service layer is fronted by a [Java Public API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Reference/Java-Foundation-API), which we will ensure backward compatible with previous releases. Before we remove any methods there will first be a release containing that method deprecated to allow third party integrations to migrate to a new method.  The Java Public API also includes a set of POJO objects which are needed to communicate with the services. It is easy to identify classes that are part of the Java Public API as they are annotated `@AlfrescoPublicApi`. | ||||
| The Java service layer is fronted by a [Java Public API](https://support.hyland.com/access?dita:id=lol1721390191517&vrm_version=25.2), which we will ensure backward compatible with previous releases. Before we remove any methods there will first be a release containing that method deprecated to allow third party integrations to migrate to a new method.  The Java Public API also includes a set of POJO objects which are needed to communicate with the services. It is easy to identify classes that are part of the Java Public API as they are annotated `@AlfrescoPublicApi`. | ||||
|  | ||||
| Each Java service will have at least four beans defined for it: | ||||
|  | ||||
| @@ -61,7 +61,7 @@ Each Java service will have at least four beans defined for it: | ||||
| #### DAOs | ||||
| The DAOs are not part of the Java Public API, but handle CRUD operations against RM stored data. We have some custom queries to improve performance for particularly heavy operations. | ||||
|  | ||||
| We use standard Alfresco [data modelling](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Content-Model-Extension-Point) to store RM metadata. We extend the [Alfresco patching mechanism](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Patches) to provide community and enterprise schema upgrades. | ||||
| We use standard Alfresco [data modelling](https://support.hyland.com/access?dita:id=ekx1720080373621&vrm_version=25.2) to store RM metadata. We extend the [Alfresco patching mechanism](https://support.hyland.com/access?dita:id=ato1720080396825&vrm_version=25.2) to provide community and enterprise schema upgrades. | ||||
|  | ||||
| *** | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -78,6 +78,12 @@ | ||||
|       <property name="transactionService" ref="transactionService" /> | ||||
|    </bean> | ||||
|  | ||||
|     <bean class="org.alfresco.rm.rest.api.fileplans.FilePlanRolesRelation"> | ||||
|         <property name="apiUtils" ref="apiUtils" /> | ||||
|         <property name="rmRoles" ref="rm.roles" /> | ||||
|         <property name="filePlanService" ref="FilePlanService" /> | ||||
|     </bean> | ||||
|  | ||||
|    <bean class="org.alfresco.rm.rest.api.holds.HoldsEntityResource" > | ||||
|       <property name="holdService" ref="HoldService" /> | ||||
|       <property name="apiUtils" ref="apiUtils" /> | ||||
| @@ -228,6 +234,11 @@ | ||||
|         <property name="siteSurfConfig" ref="rm.siteSurfConfig" /> | ||||
|    </bean> | ||||
|  | ||||
|     <bean id="rm.roles" class="org.alfresco.rm.rest.api.impl.RMRolesImpl"> | ||||
|         <property name="nodesModelFactory" ref="nodesModelFactory" /> | ||||
|         <property name="filePlanRoleService" ref="FilePlanRoleService"/> | ||||
|     </bean> | ||||
|  | ||||
|     <bean id="rm.siteSurfConfig" class="org.alfresco.rest.api.impl.SiteSurfConfig"> | ||||
|         <property name="configPath" value="alfresco/module/org_alfresco_module_rm/bootstrap/site"/> | ||||
|     </bean> | ||||
| @@ -280,4 +291,4 @@ | ||||
|       <property name="beanName" value="restJsonModule" /> | ||||
|       <property name="extendingBeanName" value="rm.restJsonModule" /> | ||||
|    </bean> | ||||
| </beans> | ||||
| </beans> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <properties> | ||||
| @@ -84,11 +84,6 @@ | ||||
|          <artifactId>junit</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.postgresql</groupId> | ||||
|          <artifactId>postgresql</artifactId> | ||||
|   | ||||
| @@ -0,0 +1,56 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api; | ||||
|  | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| /** | ||||
|  * RM Roles API | ||||
|  */ | ||||
| public interface RMRoles | ||||
| { | ||||
|  | ||||
|     String PARAM_INCLUDE_ASSIGNED_USERS = "assignedUsers"; | ||||
|     String PARAM_INCLUDE_ASSIGNED_GROUPS = "assignedGroups"; | ||||
|     String PARAM_INCLUDE_SYSTEM_ROLES = "systemRoles"; | ||||
|     String PARAM_CAPABILITY_NAME = "capabilityName"; | ||||
|     String PARAM_PERSON_ID = "personId"; | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of roles. | ||||
|      * | ||||
|      * @param filePlan | ||||
|      *            the file plan node reference | ||||
|      * @param parameters | ||||
|      *            the {@link Parameters} object to get the parameters passed into the request including: - filter, sort & paging params (where, orderBy, skipCount, maxItems) - include param (personId, includeSystemRoles) | ||||
|      * @return a paged list of {@code org.alfresco.rm.rest.api.model.RoleModel} objects | ||||
|      */ | ||||
|     CollectionWithPagingInfo<RoleModel> getRoles(NodeRef filePlan, Parameters parameters); | ||||
| } | ||||
| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.fileplans; | ||||
|  | ||||
| import static org.alfresco.util.ParameterCheck.mandatory; | ||||
|  | ||||
| import org.springframework.beans.factory.InitializingBean; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; | ||||
| import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; | ||||
| import org.alfresco.rest.framework.resource.RelationshipResource; | ||||
| import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.RMRoles; | ||||
| import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| @RelationshipResource(name = "roles", entityResource = FilePlanEntityResource.class, title = "Roles in a file plan") | ||||
| public class FilePlanRolesRelation implements RelationshipResourceAction.Read<RoleModel>, InitializingBean | ||||
| { | ||||
|     private RMRoles rmRoles; | ||||
|     private FilePlanService filePlanService; | ||||
|     private FilePlanComponentsApiUtils apiUtils; | ||||
|  | ||||
|     @Override | ||||
|     public void afterPropertiesSet() throws Exception | ||||
|     { | ||||
|         mandatory("rmRoles", this.rmRoles); | ||||
|         mandatory("apiUtils", this.apiUtils); | ||||
|         mandatory("filePlanService", this.filePlanService); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public CollectionWithPagingInfo<RoleModel> readAll(String filePlanId, Parameters params) | ||||
|     { | ||||
|         NodeRef filePlanNodeRef = getFilePlan(filePlanId); | ||||
|         if (filePlanNodeRef == null) | ||||
|         { | ||||
|             throw new EntityNotFoundException(filePlanId); | ||||
|         } | ||||
|  | ||||
|         return rmRoles.getRoles(filePlanNodeRef, params); | ||||
|     } | ||||
|  | ||||
|     private NodeRef getFilePlan(String filePlanId) | ||||
|     { | ||||
|         NodeRef filePlanNodeRef = apiUtils.lookupAndValidateNodeType(filePlanId, RecordsManagementModel.TYPE_FILE_PLAN); | ||||
|         if (!FilePlanComponentsApiUtils.FILE_PLAN_ALIAS.equals(filePlanId)) | ||||
|         { | ||||
|             filePlanNodeRef = filePlanService.getFilePlan(filePlanNodeRef); | ||||
|         } | ||||
|         return filePlanNodeRef; | ||||
|     } | ||||
|  | ||||
|     public void setRmRoles(RMRoles rmRoles) | ||||
|     { | ||||
|         this.rmRoles = rmRoles; | ||||
|     } | ||||
|  | ||||
|     public void setApiUtils(FilePlanComponentsApiUtils apiUtils) | ||||
|     { | ||||
|         this.apiUtils = apiUtils; | ||||
|     } | ||||
|  | ||||
|     public void setFilePlanService(FilePlanService filePlanService) | ||||
|     { | ||||
|         this.filePlanService = filePlanService; | ||||
|     } | ||||
| } | ||||
| @@ -30,6 +30,7 @@ package org.alfresco.rm.rest.api.impl; | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @@ -42,12 +43,15 @@ import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Capability; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Group; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinitionImpl; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent; | ||||
| import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.rest.api.Nodes; | ||||
| import org.alfresco.rest.api.model.AssocChild; | ||||
| import org.alfresco.rest.api.model.ContentInfo; | ||||
| @@ -55,7 +59,9 @@ import org.alfresco.rest.api.model.Node; | ||||
| import org.alfresco.rest.api.model.UserInfo; | ||||
| import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.model.CapabilityModel; | ||||
| import org.alfresco.rm.rest.api.model.FilePlan; | ||||
| import org.alfresco.rm.rest.api.model.GroupModel; | ||||
| import org.alfresco.rm.rest.api.model.HoldModel; | ||||
| import org.alfresco.rm.rest.api.model.RMNode; | ||||
| import org.alfresco.rm.rest.api.model.Record; | ||||
| @@ -66,6 +72,7 @@ import org.alfresco.rm.rest.api.model.RetentionPeriod; | ||||
| import org.alfresco.rm.rest.api.model.RetentionSchedule; | ||||
| import org.alfresco.rm.rest.api.model.RetentionScheduleActionDefinition; | ||||
| import org.alfresco.rm.rest.api.model.RetentionSteps; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.rm.rest.api.model.Transfer; | ||||
| import org.alfresco.rm.rest.api.model.TransferChild; | ||||
| import org.alfresco.rm.rest.api.model.TransferContainer; | ||||
| @@ -696,6 +703,36 @@ public class ApiNodesModelFactory | ||||
|                 (String) info.getProperties().get(RecordsManagementModel.PROP_HOLD_REASON)); | ||||
|     } | ||||
|  | ||||
|     public RoleModel createRoleModel(Role role, List<String> assignedUsers, List<String> assignedGroups) | ||||
|     { | ||||
|         return new RoleModel(role.getName(), | ||||
|                 role.getDisplayLabel(), | ||||
|                 role.getCapabilities() | ||||
|                         .stream() | ||||
|                         .map(this::createCapabilityModel) | ||||
|                         .sorted(Comparator.comparing(CapabilityModel::name)) | ||||
|                         .toList(), | ||||
|                 role.getRoleGroupName(), | ||||
|                 role.getGroupShortName(), | ||||
|                 assignedUsers, | ||||
|                 assignedGroups); | ||||
|     } | ||||
|  | ||||
|     public CapabilityModel createCapabilityModel(Capability capability) | ||||
|     { | ||||
|         return new CapabilityModel(capability.getName(), capability.getTitle(), capability.getDescription(), | ||||
|                 createGroupModel(capability.getGroup()), capability.getIndex()); | ||||
|     } | ||||
|  | ||||
|     public GroupModel createGroupModel(Group group) | ||||
|     { | ||||
|         if (group == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         return new GroupModel(group.getId(), group.getTitle()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates an object of type FilePlan | ||||
|      * | ||||
|   | ||||
| @@ -0,0 +1,264 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.impl; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.rest.antlr.WhereClauseParser; | ||||
| import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rest.framework.resource.parameters.where.Query; | ||||
| import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; | ||||
| import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; | ||||
| import org.alfresco.rm.rest.api.RMRoles; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| public class RMRolesImpl implements RMRoles | ||||
| { | ||||
|     private ApiNodesModelFactory nodesModelFactory; | ||||
|     private FilePlanRoleService filePlanRoleService; | ||||
|  | ||||
|     private static final Set<String> LIST_ROLES_QUERY_PROPERTIES = new HashSet<>(List.of(PARAM_PERSON_ID, PARAM_INCLUDE_SYSTEM_ROLES, PARAM_CAPABILITY_NAME)); | ||||
|  | ||||
|     @Override | ||||
|     public CollectionWithPagingInfo<RoleModel> getRoles(NodeRef filePlan, Parameters parameters) | ||||
|     { | ||||
|         var rolesFilter = getRolesFilter(parameters.getQuery()); | ||||
|         var roles = getRolesByFilter(filePlan, rolesFilter); | ||||
|  | ||||
|         var filteredRoles = roles.stream() | ||||
|                 .map(role -> createRoleModel(filePlan, role, parameters.getInclude())) | ||||
|                 .filter(hasRoleCapabilities(rolesFilter.getCapabilities())) | ||||
|                 .toList(); | ||||
|         var page = filteredRoles | ||||
|                 .stream() | ||||
|                 .sorted(Comparator.comparing(RoleModel::name)) | ||||
|                 .skip(parameters.getPaging().getSkipCount()) | ||||
|                 .limit(parameters.getPaging().getMaxItems()) | ||||
|                 .collect(Collectors.toCollection(LinkedList::new)); | ||||
|  | ||||
|         int totalItems = filteredRoles.size(); | ||||
|         boolean hasMore = parameters.getPaging().getSkipCount() + parameters.getPaging().getMaxItems() < totalItems; | ||||
|         return CollectionWithPagingInfo.asPaged(parameters.getPaging(), page, hasMore, totalItems); | ||||
|     } | ||||
|  | ||||
|     private Predicate<RoleModel> hasRoleCapabilities(List<String> capabilities) | ||||
|     { | ||||
|         return role -> capabilities == null || | ||||
|                 capabilities.isEmpty() || | ||||
|                 role.capabilities().stream().anyMatch(capability -> capabilities.contains(capability.name())); | ||||
|     } | ||||
|  | ||||
|     private Set<Role> getRolesByFilter(NodeRef filePlan, RolesFilter rolesFilter) | ||||
|     { | ||||
|         if (rolesFilter.getPersonId() != null) | ||||
|         { | ||||
|             return filePlanRoleService.getRolesByUser(filePlan, rolesFilter.getPersonId(), rolesFilter.includeSystemRoles()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return filePlanRoleService.getRoles(filePlan, rolesFilter.includeSystemRoles()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private RoleModel createRoleModel(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         List<String> assignedUsers = getAssignedUsers(filePlan, role, include); | ||||
|         List<String> assignedGroups = getAssignedGroups(filePlan, role, include); | ||||
|  | ||||
|         return nodesModelFactory.createRoleModel(role, assignedUsers, assignedGroups); | ||||
|     } | ||||
|  | ||||
|     private List<String> getAssignedUsers(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         if (include != null && include.contains(PARAM_INCLUDE_ASSIGNED_USERS)) | ||||
|         { | ||||
|             return new ArrayList<>(filePlanRoleService.getAllAssignedToRole(filePlan, role.getName())); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private List<String> getAssignedGroups(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         if (include != null && include.contains(PARAM_INCLUDE_ASSIGNED_GROUPS)) | ||||
|         { | ||||
|             return new ArrayList<>(filePlanRoleService.getGroupsAssignedToRole(filePlan, role.getName())); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory) | ||||
|     { | ||||
|         this.nodesModelFactory = nodesModelFactory; | ||||
|     } | ||||
|  | ||||
|     public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService) | ||||
|     { | ||||
|         this.filePlanRoleService = filePlanRoleService; | ||||
|     } | ||||
|  | ||||
|     private RolesFilter getRolesFilter(Query queryParameters) | ||||
|     { | ||||
|         var rolesFilterBuilder = RolesFilter.builder(); | ||||
|  | ||||
|         if (queryParameters != null) | ||||
|         { | ||||
|             var propertyWalker = new RolesQueryWalker(); | ||||
|             QueryHelper.walk(queryParameters, propertyWalker); | ||||
|  | ||||
|             rolesFilterBuilder | ||||
|                     .withPersonId(propertyWalker.getPersonId()) | ||||
|                     .withCapabilities(propertyWalker.getCapabilitiesNames()) | ||||
|                     .withIncludeSystemRoles(propertyWalker.includeSystemRoles()); | ||||
|         } | ||||
|         return rolesFilterBuilder.build(); | ||||
|     } | ||||
|  | ||||
|     private static class RolesQueryWalker extends MapBasedQueryWalker | ||||
|     { | ||||
|         private List<String> capabilitiesNames; | ||||
|  | ||||
|         public RolesQueryWalker() | ||||
|         { | ||||
|             super(LIST_ROLES_QUERY_PROPERTIES, null); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void in(String propertyName, boolean negated, String... propertyValues) | ||||
|         { | ||||
|             if (negated) | ||||
|             { | ||||
|                 throw new InvalidArgumentException("Cannot use NOT for " + propertyName); | ||||
|             } | ||||
|  | ||||
|             if (PARAM_CAPABILITY_NAME.equalsIgnoreCase(propertyName)) | ||||
|             { | ||||
|                 capabilitiesNames = Arrays.asList(propertyValues); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void and() | ||||
|         { | ||||
|             // allow AND, e.g. personId='123' AND includeSystemRoles=true | ||||
|         } | ||||
|  | ||||
|         public List<String> getCapabilitiesNames() | ||||
|         { | ||||
|             return this.capabilitiesNames; | ||||
|         } | ||||
|  | ||||
|         public String getPersonId() | ||||
|         { | ||||
|             return getProperty(PARAM_PERSON_ID, WhereClauseParser.EQUALS, String.class); | ||||
|         } | ||||
|  | ||||
|         public Boolean includeSystemRoles() | ||||
|         { | ||||
|             return getProperty(PARAM_INCLUDE_SYSTEM_ROLES, WhereClauseParser.EQUALS, Boolean.class); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| class RolesFilter | ||||
| { | ||||
|     private String personId; | ||||
|     private boolean includeSystemRoles; | ||||
|     private List<String> capabilities; | ||||
|  | ||||
|     private RolesFilter() | ||||
|     {} | ||||
|  | ||||
|     public static RolesFilterBuilder builder() | ||||
|     { | ||||
|         return new RolesFilterBuilder(); | ||||
|     } | ||||
|  | ||||
|     public String getPersonId() | ||||
|     { | ||||
|         return personId; | ||||
|     } | ||||
|  | ||||
|     public boolean includeSystemRoles() | ||||
|     { | ||||
|         return includeSystemRoles; | ||||
|     } | ||||
|  | ||||
|     public List<String> getCapabilities() | ||||
|     { | ||||
|         return capabilities; | ||||
|     } | ||||
|  | ||||
|     public static class RolesFilterBuilder | ||||
|     { | ||||
|         private String personId; | ||||
|         private boolean includeSystemRoles = true; | ||||
|         private List<String> capabilities; | ||||
|  | ||||
|         public RolesFilterBuilder withPersonId(String personId) | ||||
|         { | ||||
|             this.personId = personId; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilterBuilder withIncludeSystemRoles(Boolean includeSystemRoles) | ||||
|         { | ||||
|             if (includeSystemRoles != null) | ||||
|             { | ||||
|                 this.includeSystemRoles = includeSystemRoles; | ||||
|             } | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilterBuilder withCapabilities(List<String> capabilities) | ||||
|         { | ||||
|             this.capabilities = capabilities; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilter build() | ||||
|         { | ||||
|             RolesFilter rolesFilter = new RolesFilter(); | ||||
|             rolesFilter.personId = this.personId; | ||||
|             rolesFilter.includeSystemRoles = this.includeSystemRoles; | ||||
|             rolesFilter.capabilities = this.capabilities; | ||||
|             return rolesFilter; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| public record CapabilityModel(String name, String title, String description, GroupModel group, int index) | ||||
| {} | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| public record GroupModel(String id, String title) | ||||
| {} | ||||
| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public record RoleModel(String name, String displayLabel, List<CapabilityModel> capabilities, String roleGroupName, String groupShortName, List<String> assignedUsers, List<String> assignedGroups) | ||||
| {} | ||||
| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public record RoleModelList(List<RoleModel> roleModelList) | ||||
| {} | ||||
| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Package info that defines the Information Governance Roles REST API | ||||
|  * | ||||
|  * @author Damian Ujma | ||||
|  */ | ||||
| @WebApi(name = "gs", scope = Api.SCOPE.PUBLIC, version = 1) | ||||
| package org.alfresco.rm.rest.api.roles; | ||||
|  | ||||
| import org.alfresco.rest.framework.Api; | ||||
| import org.alfresco.rest.framework.WebApi; | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -0,0 +1,177 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.impl; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Capability; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Paging; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; | ||||
| import org.alfresco.rm.rest.api.model.CapabilityModel; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.mockito.Mockito.*; | ||||
|  | ||||
| public class RMRolesImplUnitTest extends BaseUnitTest { | ||||
|  | ||||
|     private final RecognizedParamsExtractor queryExtractor = new RecognizedParamsExtractor() {}; | ||||
|  | ||||
|     private RMRolesImpl rmRolesImpl; | ||||
|     private FilePlanRoleService mockedFilePlanRoleService; | ||||
|     private ApiNodesModelFactory mockedNodesModelFactory; | ||||
|  | ||||
|     private final Capability viewRecordsCapability = mock(Capability.class); | ||||
|     private final Capability editMetadataCapability = mock(Capability.class); | ||||
|  | ||||
|     private final Role role1 = new Role("Role1", "Role 1", Set.of(viewRecordsCapability), "Group1"); | ||||
|     private final Role role2 = new Role("Role2", "Role 2", Set.of(editMetadataCapability), "Group2"); | ||||
|  | ||||
|     private final RoleModel roleModel1 = new RoleModel("Role1", "Role 1", List.of(new CapabilityModel("ViewRecords", "", "", null, 0)), "Group1", null, List.of("User1"), List.of("Group1")); | ||||
|     private final RoleModel roleModel2 = new RoleModel("Role2", "Role 2", List.of(new CapabilityModel("EditMetadata", "", "", null, 0)), "Group2", null, List.of("User2"), List.of("Group2")); | ||||
|  | ||||
|     private final NodeRef filePlan = new NodeRef("workspace://SpacesStore/testFilePlan"); | ||||
|  | ||||
|     private final Parameters parameters = mock(Parameters.class); | ||||
|     private final Paging paging = mock(Paging.class); | ||||
|  | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         mockedFilePlanRoleService = mock(FilePlanRoleService.class); | ||||
|         mockedNodesModelFactory = mock(ApiNodesModelFactory.class); | ||||
|  | ||||
|         rmRolesImpl = new RMRolesImpl(); | ||||
|         rmRolesImpl.setFilePlanRoleService(mockedFilePlanRoleService); | ||||
|         rmRolesImpl.setNodesModelFactory(mockedNodesModelFactory); | ||||
|  | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, true)).thenReturn(Set.of(role1, role2)); | ||||
|         when(mockedNodesModelFactory.createRoleModel(eq(role1), any(), any())).thenReturn(roleModel1); | ||||
|         when(mockedNodesModelFactory.createRoleModel(eq(role2), any(), any())).thenReturn(roleModel2); | ||||
|  | ||||
|         when(viewRecordsCapability.getName()).thenReturn("ViewRecords"); | ||||
|         when(editMetadataCapability.getName()).thenReturn("EditMetadata"); | ||||
|  | ||||
|         when(parameters.getPaging()).thenReturn(paging); | ||||
|         when(paging.getSkipCount()).thenReturn(0); | ||||
|         when(paging.getMaxItems()).thenReturn(10); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_NoFilters() { | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         List<RoleModel> roleModelList = (List<RoleModel>) result.getCollection(); | ||||
|         assertEquals(2, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1, roleModel2), roleModelList); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role2), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_WithPersonId() { | ||||
|         // given | ||||
|         String personId = "testUser"; | ||||
|         when(mockedFilePlanRoleService.getRolesByUser(filePlan, personId, true)).thenReturn(Set.of(role1)); | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(personId='" + personId + "')")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRolesByUser(filePlan, personId, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetNonSystemRoles() { | ||||
|         //given | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, false)).thenReturn(Set.of(role2)); | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(systemRoles=false)")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel2), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, false); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role2), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_WithCapabilitiesFilter() { | ||||
|         // given | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(capabilityName IN ('ViewRecords'))")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_IncludeAssignedUsersAndGroups() { | ||||
|         // given | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, true)).thenReturn(Set.of(role1)); | ||||
|         when(mockedFilePlanRoleService.getAllAssignedToRole(filePlan, "Role1")).thenReturn(Set.of("User1")); | ||||
|         when(mockedFilePlanRoleService.getGroupsAssignedToRole(filePlan, "Role1")).thenReturn(Set.of("Group1")); | ||||
|  | ||||
|         when(parameters.getInclude()).thenReturn(List.of("assignedUsers", "assignedGroups")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         List<RoleModel> roleModelList = (List<RoleModel>) result.getCollection(); | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), roleModelList); | ||||
|         assertEquals(List.of("User1"), roleModelList.get(0).assignedUsers()); | ||||
|         assertEquals(List.of("Group1"), roleModelList.get(0).assignedGroups()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedFilePlanRoleService).getAllAssignedToRole(filePlan, "Role1"); | ||||
|         verify(mockedFilePlanRoleService).getGroupsAssignedToRole(filePlan, "Role1"); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(role1, List.of("User1"), List.of("Group1")); | ||||
|     } | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -540,6 +540,66 @@ paths: | ||||
|           description: Unexpected error | ||||
|           schema: | ||||
|             $ref: '#/definitions/Error' | ||||
|   '/file-plans/{filePlanId}/roles': | ||||
|     get: | ||||
|       tags: | ||||
|         - file-plans | ||||
|       summary: Get roles in a file plan | ||||
|       description: | | ||||
|         Gets a list of roles for the specified file plan **filePlanId**. | ||||
|          | ||||
|         You can use the **include** parameter to return additional information. | ||||
|          | ||||
|         The **where** parameter can also be used to filter by **personId**, **systemRoles** and **capabilityName**. | ||||
|  | ||||
|         You can use the **where** parameter to  | ||||
|         * filter roles by user: | ||||
|         `where=(personId='admin')` | ||||
|          | ||||
|         * not include system roles in the results: | ||||
|         `where=(systemRoles=false)` | ||||
|          | ||||
|         * filter roles by specified capabilities: | ||||
|         `where=(capabilityName in ('AddToHold', 'ViewRecords'))` | ||||
|          | ||||
|         This may be combined with all filter, as shown below: | ||||
|          | ||||
|         `where=(systemRoles=false and personId='johndoe' and capabilityName in ('AddToHold', 'ViewRecords'))` | ||||
|  | ||||
|       operationId: getFilePlanRoles | ||||
|       parameters: | ||||
|         - $ref: '#/parameters/filePlanIdWithAliasParam' | ||||
|         - $ref: '#/parameters/whereParam' | ||||
|         - $ref: '#/parameters/rolesIncludeParam' | ||||
|         - $ref: '#/parameters/skipCountParam' | ||||
|         - $ref: '#/parameters/maxItemsParam' | ||||
|       produces: | ||||
|         - application/json | ||||
|       responses: | ||||
|         '200': | ||||
|           description: Successful response | ||||
|           schema: | ||||
|             type: object | ||||
|             properties: | ||||
|               list: | ||||
|                 type: array | ||||
|                 items: | ||||
|                   $ref: '#/definitions/RoleModel' | ||||
|               pagination: | ||||
|                 $ref: '#/definitions/Pagination' | ||||
|         '400': | ||||
|           description: | | ||||
|             Invalid parameter: value of **maxItems** or **skipCount**, or **include**, or **where** is invalid | ||||
|         '401': | ||||
|           description: Authentication failed | ||||
|         '403': | ||||
|           description: Current user does not have permission to read **filePlanId** | ||||
|         '404': | ||||
|           description: "**filePlanId** does not exist" | ||||
|         default: | ||||
|           description: Unexpected error | ||||
|           schema: | ||||
|             $ref: '#/definitions/Error' | ||||
|   ## Unfiled records containers | ||||
|   '/unfiled-containers/{unfiledContainerId}': | ||||
|     get: | ||||
| @@ -3307,6 +3367,21 @@ parameters: | ||||
|       * actions | ||||
|     required: false | ||||
|     type: string | ||||
|   rolesIncludeParam: | ||||
|     name: include | ||||
|     in: query | ||||
|     description: | | ||||
|       Returns additional information about roles. Any optional field from the response model can be requested. For example: | ||||
|       * assignedUsers | ||||
|       * assignedGroups | ||||
|     required: false | ||||
|     type: string | ||||
|   whereParam: | ||||
|     name: where | ||||
|     in: query | ||||
|     description: A string to restrict the returned objects by using a predicate. | ||||
|     required: false | ||||
|     type: string | ||||
| definitions: | ||||
|   FilePlanComponentBodyUpdate: | ||||
|     type: object | ||||
| @@ -4389,6 +4464,49 @@ definitions: | ||||
|       query: | ||||
|         description: The query which may have been generated in some way from the userQuery | ||||
|         type: string | ||||
|   CapabilityModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       name: | ||||
|         type: string | ||||
|       title: | ||||
|         type: string | ||||
|       description: | ||||
|         type: string | ||||
|       group: | ||||
|         $ref: '#/definitions/GroupModel' | ||||
|       index: | ||||
|         type: integer | ||||
|   GroupModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       id: | ||||
|         type: string | ||||
|       title: | ||||
|         type: string | ||||
|   RoleModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       name: | ||||
|         type: string | ||||
|       displayLabel: | ||||
|         type: string | ||||
|       capabilities: | ||||
|         type: array | ||||
|         items: | ||||
|           $ref: '#/definitions/CapabilityModel' | ||||
|       roleGroupName: | ||||
|         type: string | ||||
|       groupShortName: | ||||
|         type: string | ||||
|       assignedUsers: | ||||
|         type: array | ||||
|         items: | ||||
|           type: string | ||||
|       assignedGroups: | ||||
|         type: array | ||||
|         items: | ||||
|           type: string | ||||
|   HoldBulkOperation: | ||||
|     type: object | ||||
|     properties: | ||||
| @@ -4929,4 +5047,4 @@ definitions: | ||||
|           - SiteConsumer | ||||
|           - SiteCollaborator | ||||
|           - SiteContributor | ||||
|           - SiteManager | ||||
|           - SiteManager | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -70,11 +70,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.postgresql</groupId> | ||||
|             <artifactId>postgresql</artifactId> | ||||
|   | ||||
| @@ -80,6 +80,11 @@ function runAction(p_params) | ||||
|          { | ||||
|             result.fileExist = true; | ||||
|          } | ||||
|          if (error.indexOf("FolderExistsException") != -1) | ||||
|          { | ||||
|             result.fileExist = true; | ||||
|             result.type = "folder"; | ||||
|          } | ||||
|       } | ||||
|        | ||||
|       results.push(result); | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo</artifactId> | ||||
|       <version>25.2.0.27</version> | ||||
|       <version>25.2.0.52-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <dependencies> | ||||
| @@ -126,11 +126,6 @@ | ||||
|          <artifactId>junit</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.mockito</groupId> | ||||
|          <artifactId>mockito-core</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -247,11 +247,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.antlr</groupId> | ||||
|             <artifactId>gunit</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -46,11 +46,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-core</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,6 +9,6 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
| </project> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -49,5 +49,6 @@ then | ||||
|   echo "Docker Compose started ok" | ||||
| else | ||||
|   echo "Docker Compose failed to start" >&2 | ||||
|   docker compose ${DOCKER_COMPOSES} logs --tail 200 | ||||
|   exit 1 | ||||
| fi | ||||
| fi | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| **TAS**( **T**est **A**utomation **S**ystem)- **CMIS** is the project that handles the automated tests related only to CMIS API integrated with Alfresco One [Alfresco CMIS API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Reference/CMIS-API).  | ||||
| **TAS**( **T**est **A**utomation **S**ystem)- **CMIS** is the project that handles the automated tests related only to CMIS API integrated with Alfresco One [Alfresco CMIS API](https://support.hyland.com/access?dita:id=kvf1721390177551&vrm_version=25.2).  | ||||
|  | ||||
| It is based on Apache Maven, compatible with major IDEs and is using also Spring capabilities for dependency injection. | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <organization> | ||||
| @@ -68,16 +68,6 @@ | ||||
|                 </exclusion> | ||||
|             </exclusions> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -36,11 +36,6 @@ | ||||
|             <artifactId>jakarta.mail-api</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -44,18 +44,6 @@ | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.sun.mail</groupId> | ||||
|             <artifactId>jakarta.mail</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -79,18 +79,6 @@ | ||||
|             <version>${commons-lang3.version}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>org.awaitility</groupId> | ||||
|             <artifactId>awaitility</artifactId> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -747,7 +747,7 @@ public class CreateRulesTests extends RulesRestTest | ||||
|                 .createSingleRule(ruleModel); | ||||
|  | ||||
|         restClient.assertStatusCodeIs(NOT_FOUND); | ||||
|         restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found"); | ||||
|         restClient.assertLastError().containsSummary("Destination folder having Id: non-existent-node no longer exists. Please update your rule definition."); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -31,11 +31,6 @@ | ||||
|             <artifactId>webdav</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
							
								
								
									
										32
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>alfresco-community-repo</artifactId> | ||||
|     <version>25.2.0.27</version> | ||||
|     <version>25.2.0.52-SNAPSHOT</version> | ||||
|     <packaging>pom</packaging> | ||||
|     <name>Alfresco Community Repo Parent</name> | ||||
|  | ||||
| @@ -51,8 +51,8 @@ | ||||
|         <dependency.alfresco-server-root.version>7.0.2</dependency.alfresco-server-root.version> | ||||
|         <dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version> | ||||
|         <dependency.activiti.version>5.23.0</dependency.activiti.version> | ||||
|         <dependency.alfresco-transform-core.version>5.1.7</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.1.7</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-transform-core.version>5.1.8-A.2</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.1.8-A.2</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version> | ||||
|         <dependency.acs-event-model.version>1.0.2</dependency.acs-event-model.version> | ||||
|  | ||||
| @@ -74,8 +74,9 @@ | ||||
|         <dependency.guava.version>33.3.1-jre</dependency.guava.version> | ||||
|         <dependency.httpclient.version>4.5.14</dependency.httpclient.version> | ||||
|         <dependency.httpcore.version>4.4.16</dependency.httpcore.version> | ||||
|         <dependency.httpcomponents-httpclient5.version>5.4.1</dependency.httpcomponents-httpclient5.version> | ||||
|         <dependency.httpcomponents-httpcore5.version>5.3.3</dependency.httpcomponents-httpcore5.version> | ||||
|         <dependency.httpcomponents-httpclient5.version>5.5</dependency.httpcomponents-httpclient5.version> | ||||
|         <dependency.httpcomponents-httpcore5.version>5.3.4</dependency.httpcomponents-httpcore5.version> | ||||
|         <dependency.httpcomponents-httpcore5-h2.version>5.3.4</dependency.httpcomponents-httpcore5-h2.version> | ||||
|         <dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version> | ||||
|         <dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version> | ||||
|         <dependency.slf4j.version>2.0.16</dependency.slf4j.version> | ||||
| @@ -153,7 +154,7 @@ | ||||
|         <connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection> | ||||
|         <developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection> | ||||
|         <url>https://github.com/Alfresco/alfresco-community-repo</url> | ||||
|         <tag>25.2.0.27</tag> | ||||
|         <tag>HEAD</tag> | ||||
|     </scm> | ||||
|  | ||||
|     <distributionManagement> | ||||
| @@ -400,6 +401,11 @@ | ||||
|                 <artifactId>httpcore5</artifactId> | ||||
|                 <version>${dependency.httpcomponents-httpcore5.version}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>org.apache.httpcomponents.core5</groupId> | ||||
|                 <artifactId>httpcore5-h2</artifactId> | ||||
|                 <version>${dependency.httpcomponents-httpcore5-h2.version}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-logging</groupId> | ||||
|                 <artifactId>commons-logging</artifactId> | ||||
| @@ -408,7 +414,7 @@ | ||||
|             <dependency> | ||||
|                 <groupId>commons-beanutils</groupId> | ||||
|                 <artifactId>commons-beanutils</artifactId> | ||||
|                 <version>1.9.4</version> | ||||
|                 <version>1.11.0</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-codec</groupId> | ||||
| @@ -822,18 +828,6 @@ | ||||
|                 <version>4.13.2</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>com.epam.reportportal</groupId> | ||||
|                 <artifactId>agent-java-testng</artifactId> | ||||
|                 <version>5.4.0</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>com.squareup.okhttp3</groupId> | ||||
|                 <artifactId>okhttp</artifactId> | ||||
|                 <version>4.12.0</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>org.antlr</groupId> | ||||
|                 <artifactId>gunit</artifactId> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -66,11 +66,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-core</artifactId> | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Remote API | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2023 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software.  | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of  | ||||
| @@ -46,7 +46,7 @@ import org.alfresco.repo.management.subsystems.ActivateableBean; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationComponent; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationException; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationUtil; | ||||
| import org.alfresco.repo.security.authentication.external.AdminConsoleAuthenticator; | ||||
| import org.alfresco.repo.security.authentication.external.ExternalUserAuthenticator; | ||||
| import org.alfresco.repo.security.authentication.external.RemoteUserMapper; | ||||
| import org.alfresco.repo.web.auth.AuthenticationListener; | ||||
| import org.alfresco.repo.web.auth.TicketCredentials; | ||||
| @@ -71,9 +71,11 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|  | ||||
|     protected RemoteUserMapper remoteUserMapper; | ||||
|     protected AuthenticationComponent authenticationComponent; | ||||
|     protected AdminConsoleAuthenticator adminConsoleAuthenticator; | ||||
|     protected ExternalUserAuthenticator adminConsoleAuthenticator; | ||||
|     protected ExternalUserAuthenticator webScriptsHomeAuthenticator; | ||||
|  | ||||
|     private boolean alwaysAllowBasicAuthForAdminConsole = true; | ||||
|     private boolean alwaysAllowBasicAuthForWebScriptsHome = true; | ||||
|     List<String> adminConsoleScriptFamilies; | ||||
|     long getRemoteUserTimeoutMilliseconds = GET_REMOTE_USER_TIMEOUT_MILLISECONDS_DEFAULT; | ||||
|  | ||||
| @@ -97,6 +99,16 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|         this.alwaysAllowBasicAuthForAdminConsole = alwaysAllowBasicAuthForAdminConsole; | ||||
|     } | ||||
|  | ||||
|     public boolean isAlwaysAllowBasicAuthForWebScriptsHome() | ||||
|     { | ||||
|         return alwaysAllowBasicAuthForWebScriptsHome; | ||||
|     } | ||||
|  | ||||
|     public void setAlwaysAllowBasicAuthForWebScriptsHome(boolean alwaysAllowBasicAuthForWebScriptsHome) | ||||
|     { | ||||
|         this.alwaysAllowBasicAuthForWebScriptsHome = alwaysAllowBasicAuthForWebScriptsHome; | ||||
|     } | ||||
|  | ||||
|     public List<String> getAdminConsoleScriptFamilies() | ||||
|     { | ||||
|         return adminConsoleScriptFamilies; | ||||
| @@ -118,11 +130,17 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|     } | ||||
|  | ||||
|     public void setAdminConsoleAuthenticator( | ||||
|             AdminConsoleAuthenticator adminConsoleAuthenticator) | ||||
|             ExternalUserAuthenticator adminConsoleAuthenticator) | ||||
|     { | ||||
|         this.adminConsoleAuthenticator = adminConsoleAuthenticator; | ||||
|     } | ||||
|  | ||||
|     public void setWebScriptsHomeAuthenticator( | ||||
|             ExternalUserAuthenticator webScriptsHomeAuthenticator) | ||||
|     { | ||||
|         this.webScriptsHomeAuthenticator = webScriptsHomeAuthenticator; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res) | ||||
|     { | ||||
| @@ -136,6 +154,8 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|      */ | ||||
|     public class RemoteUserAuthenticator extends BasicHttpAuthenticator | ||||
|     { | ||||
|         private static final String WEB_SCRIPTS_BASE_PATH = "org/springframework/extensions/webscripts"; | ||||
|  | ||||
|         public RemoteUserAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res, AuthenticationListener listener) | ||||
|         { | ||||
|             super(req, res, listener); | ||||
| @@ -156,24 +176,47 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|             { | ||||
|  | ||||
|                 if (servletReq.getServiceMatch() != null && | ||||
|                         isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive()) | ||||
|                         isAdminConsole(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive()) | ||||
|                 { | ||||
|                     userId = getAdminConsoleUser(); | ||||
|                 } | ||||
|                 else if (servletReq.getServiceMatch() != null && | ||||
|                         isWebScriptsHome(servletReq.getServiceMatch().getWebScript()) && isWebScriptsHomeAuthenticatorActive()) | ||||
|                 { | ||||
|                     userId = getWebScriptsHomeUser(); | ||||
|                 } | ||||
|  | ||||
|                 if (userId == null) | ||||
|                 { | ||||
|                     if (isAlwaysAllowBasicAuthForAdminConsole()) | ||||
|                     { | ||||
|                         final boolean useTimeoutForAdminAccessingAdminConsole = shouldUseTimeoutForAdminAccessingAdminConsole(required, isGuest); | ||||
|                         boolean shouldUseTimeout = shouldUseTimeoutForAdminAccessingAdminConsole(required, isGuest); | ||||
|  | ||||
|                         if (useTimeoutForAdminAccessingAdminConsole && isBasicAuthHeaderPresentForAdmin()) | ||||
|                         if (shouldUseTimeout && isBasicAuthHeaderPresentForAdmin()) | ||||
|                         { | ||||
|                             return callBasicAuthForAdminConsoleAccess(required, isGuest); | ||||
|                             return callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(required, isGuest); | ||||
|                         } | ||||
|                         try | ||||
|                         { | ||||
|                             userId = getRemoteUserWithTimeout(useTimeoutForAdminAccessingAdminConsole); | ||||
|                             userId = getRemoteUserWithTimeout(shouldUseTimeout); | ||||
|                         } | ||||
|                         catch (AuthenticationTimeoutException e) | ||||
|                         { | ||||
|                             // return basic auth challenge | ||||
|                             return false; | ||||
|                         } | ||||
|                     } | ||||
|                     else if (isAlwaysAllowBasicAuthForWebScriptsHome()) | ||||
|                     { | ||||
|                         boolean shouldUseTimeout = shouldUseTimeoutForAdminAccessingWebScriptsHome(required, isGuest); | ||||
|  | ||||
|                         if (shouldUseTimeout && isBasicAuthHeaderPresentForAdmin()) | ||||
|                         { | ||||
|                             return callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(required, isGuest); | ||||
|                         } | ||||
|                         try | ||||
|                         { | ||||
|                             userId = getRemoteUserWithTimeout(shouldUseTimeout); | ||||
|                         } | ||||
|                         catch (AuthenticationTimeoutException e) | ||||
|                         { | ||||
| @@ -252,38 +295,63 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|                     authenticated = super.authenticate(required, isGuest); | ||||
|                 } | ||||
|             } | ||||
|             if (!authenticated && servletReq.getServiceMatch() != null && | ||||
|                     isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript()) && isAdminConsoleAuthenticatorActive()) | ||||
|             if (!authenticated && servletReq.getServiceMatch() != null) | ||||
|             { | ||||
|                 adminConsoleAuthenticator.requestAuthentication(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse()); | ||||
|                 WebScript webScript = servletReq.getServiceMatch().getWebScript(); | ||||
|  | ||||
|                 if (isAdminConsole(webScript) && isAdminConsoleAuthenticatorActive()) | ||||
|                 { | ||||
|                     adminConsoleAuthenticator.requestAuthentication( | ||||
|                             this.servletReq.getHttpServletRequest(), | ||||
|                             this.servletRes.getHttpServletResponse()); | ||||
|                 } | ||||
|                 else if (isWebScriptsHome(webScript) | ||||
|                         && isWebScriptsHomeAuthenticatorActive()) | ||||
|                 { | ||||
|                     webScriptsHomeAuthenticator.requestAuthentication( | ||||
|                             this.servletReq.getHttpServletRequest(), | ||||
|                             this.servletRes.getHttpServletResponse()); | ||||
|                 } | ||||
|             } | ||||
|             return authenticated; | ||||
|         } | ||||
|  | ||||
|         private boolean callBasicAuthForAdminConsoleAccess(RequiredAuthentication required, boolean isGuest) | ||||
|         private boolean callBasicAuthForAdminConsoleOrWebScriptsHomeAccess(RequiredAuthentication required, boolean isGuest) | ||||
|         { | ||||
|             // return REST call, after a timeout/basic auth challenge | ||||
|             if (LOGGER.isTraceEnabled()) | ||||
|             { | ||||
|                 LOGGER.trace("An Admin Console request has come in with Basic Auth headers present for an admin user."); | ||||
|                 LOGGER.trace("An Admin Console or WebScripts Home request has come in with Basic Auth headers present for an admin user."); | ||||
|             } | ||||
|             // In order to prompt for another password, in case it was not entered correctly, | ||||
|             // the output of this method should be returned by the calling "authenticate" method; | ||||
|             // This would also mean, that once the admin basic auth header is present, | ||||
|             // the authentication chain will not be used for the admin console access | ||||
|             // the authentication chain will not be used for access | ||||
|             return super.authenticate(required, isGuest); | ||||
|         } | ||||
|  | ||||
|         private boolean shouldUseTimeoutForAdminAccessingAdminConsole(RequiredAuthentication required, boolean isGuest) | ||||
|         { | ||||
|             boolean useTimeoutForAdminAccessingAdminConsole = RequiredAuthentication.admin.equals(required) && !isGuest && | ||||
|                     servletReq.getServiceMatch() != null && isAdminConsoleWebScript(servletReq.getServiceMatch().getWebScript()); | ||||
|             boolean adminConsoleTimeout = RequiredAuthentication.admin.equals(required) && !isGuest && | ||||
|                     servletReq.getServiceMatch() != null && isAdminConsole(servletReq.getServiceMatch().getWebScript()); | ||||
|  | ||||
|             if (LOGGER.isTraceEnabled()) | ||||
|             { | ||||
|                 LOGGER.trace("Should ensure that the admins can login with basic auth: " + useTimeoutForAdminAccessingAdminConsole); | ||||
|                 LOGGER.trace("Should ensure that the admins can login with basic auth: " + adminConsoleTimeout); | ||||
|             } | ||||
|             return useTimeoutForAdminAccessingAdminConsole; | ||||
|             return adminConsoleTimeout; | ||||
|         } | ||||
|  | ||||
|         private boolean shouldUseTimeoutForAdminAccessingWebScriptsHome(RequiredAuthentication required, boolean isGuest) | ||||
|         { | ||||
|             boolean adminWebScriptsHomeTimeout = RequiredAuthentication.admin.equals(required) && !isGuest && | ||||
|                     servletReq.getServiceMatch() != null && isWebScriptsHome(servletReq.getServiceMatch().getWebScript()); | ||||
|  | ||||
|             if (LOGGER.isTraceEnabled()) | ||||
|             { | ||||
|                 LOGGER.trace("Should ensure that the admins can login with basic auth: " + adminWebScriptsHomeTimeout); | ||||
|             } | ||||
|             return adminWebScriptsHomeTimeout; | ||||
|         } | ||||
|  | ||||
|         private boolean isRemoteUserMapperActive() | ||||
| @@ -296,7 +364,12 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|             return adminConsoleAuthenticator != null && (!(adminConsoleAuthenticator instanceof ActivateableBean) || ((ActivateableBean) adminConsoleAuthenticator).isActive()); | ||||
|         } | ||||
|  | ||||
|         protected boolean isAdminConsoleWebScript(WebScript webScript) | ||||
|         private boolean isWebScriptsHomeAuthenticatorActive() | ||||
|         { | ||||
|             return webScriptsHomeAuthenticator != null && (!(webScriptsHomeAuthenticator instanceof ActivateableBean) || ((ActivateableBean) webScriptsHomeAuthenticator).isActive()); | ||||
|         } | ||||
|  | ||||
|         protected boolean isAdminConsole(WebScript webScript) | ||||
|         { | ||||
|             if (webScript == null || adminConsoleScriptFamilies == null || webScript.getDescription() == null | ||||
|                     || webScript.getDescription().getFamilys() == null) | ||||
| @@ -310,7 +383,7 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|             } | ||||
|  | ||||
|             // intersect the "family" sets defined | ||||
|             Set<String> families = new HashSet<String>(webScript.getDescription().getFamilys()); | ||||
|             Set<String> families = new HashSet<>(webScript.getDescription().getFamilys()); | ||||
|             families.retainAll(adminConsoleScriptFamilies); | ||||
|             final boolean isAdminConsole = !families.isEmpty(); | ||||
|  | ||||
| @@ -322,6 +395,23 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|             return isAdminConsole; | ||||
|         } | ||||
|  | ||||
|         protected boolean isWebScriptsHome(WebScript webScript) | ||||
|         { | ||||
|             if (webScript == null || webScript.toString() == null) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             boolean isWebScriptsHome = webScript.toString().startsWith(WEB_SCRIPTS_BASE_PATH); | ||||
|  | ||||
|             if (LOGGER.isTraceEnabled() && isWebScriptsHome) | ||||
|             { | ||||
|                 LOGGER.trace("Detected a WebScripts Home webscript: " + webScript); | ||||
|             } | ||||
|  | ||||
|             return isWebScriptsHome; | ||||
|         } | ||||
|  | ||||
|         protected String getRemoteUserWithTimeout(boolean useTimeout) throws AuthenticationTimeoutException | ||||
|         { | ||||
|             if (!useTimeout) | ||||
| @@ -417,7 +507,21 @@ public class RemoteUserAuthenticatorFactory extends BasicHttpAuthenticatorFactor | ||||
|  | ||||
|             if (isRemoteUserMapperActive()) | ||||
|             { | ||||
|                 userId = adminConsoleAuthenticator.getAdminConsoleUser(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse()); | ||||
|                 userId = adminConsoleAuthenticator.getUserId(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse()); | ||||
|             } | ||||
|  | ||||
|             logRemoteUserID(userId); | ||||
|  | ||||
|             return userId; | ||||
|         } | ||||
|  | ||||
|         protected String getWebScriptsHomeUser() | ||||
|         { | ||||
|             String userId = null; | ||||
|  | ||||
|             if (isRemoteUserMapperActive()) | ||||
|             { | ||||
|                 userId = webScriptsHomeAuthenticator.getUserId(this.servletReq.getHttpServletRequest(), this.servletRes.getHttpServletResponse()); | ||||
|             } | ||||
|  | ||||
|             logRemoteUserID(userId); | ||||
|   | ||||
| @@ -712,7 +712,7 @@ public class PeopleImpl implements People | ||||
|         Boolean isEnabled = person.isEnabled(); | ||||
|         if (isEnabled != null) | ||||
|         { | ||||
|             if (isAdminAuthority(personIdToUpdate)) | ||||
|             if (!isEnabled && isAdminAuthority(personIdToUpdate)) | ||||
|             { | ||||
|                 throw new PermissionDeniedException("Admin authority cannot be disabled."); | ||||
|             } | ||||
|   | ||||
| @@ -2,23 +2,23 @@ | ||||
|  * #%L | ||||
|  * Alfresco Remote API | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2016 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software.  | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of  | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is  | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  *  | ||||
|  * | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  *  | ||||
|  * | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  *  | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
| @@ -38,14 +38,19 @@ import java.util.Collections; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashMap; | ||||
| import java.util.Iterator; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.springframework.beans.factory.InitializingBean; | ||||
| import org.springframework.extensions.surf.util.I18NUtil; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.query.PagingRequest; | ||||
| import org.alfresco.repo.security.permissions.AccessDeniedException; | ||||
| import org.alfresco.repo.site.SiteModel; | ||||
| import org.alfresco.rest.api.Nodes; | ||||
| import org.alfresco.rest.api.People; | ||||
| @@ -89,6 +94,7 @@ import org.alfresco.util.SearchLanguageConversion; | ||||
|  */ | ||||
| public class QueriesImpl implements Queries, InitializingBean | ||||
| { | ||||
|     private static final Log LOGGER = LogFactory.getLog(QueriesImpl.class); | ||||
|     private final static Map<String, QName> NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames( | ||||
|             PARAM_NAME, ContentModel.PROP_NAME, | ||||
|             PARAM_CREATEDAT, ContentModel.PROP_CREATED, | ||||
| @@ -247,7 +253,7 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|                             { | ||||
|                                 // first request for this namespace prefix, get and cache result | ||||
|                                 Collection<String> prefixes = namespaceService.getPrefixes(qname.getNamespaceURI()); | ||||
|                                 prefix = prefixes.size() != 0 ? prefixes.iterator().next() : ""; | ||||
|                                 prefix = !prefixes.isEmpty() ? prefixes.iterator().next() : ""; | ||||
|                                 cache.put(qname.getNamespaceURI(), prefix); | ||||
|                             } | ||||
|                             buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName())); | ||||
| @@ -261,12 +267,6 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|                 return buf.toString(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected List<Node> newList(int capacity) | ||||
|             { | ||||
|                 return new ArrayList<Node>(capacity); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected Node convert(NodeRef nodeRef, List<String> includeParam) | ||||
|             { | ||||
| @@ -303,18 +303,11 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|                 query.append("*\")"); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected List<Person> newList(int capacity) | ||||
|             { | ||||
|                 return new ArrayList<Person>(capacity); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected Person convert(NodeRef nodeRef, List<String> includeParam) | ||||
|             { | ||||
|                 String personId = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME); | ||||
|                 Person person = people.getPerson(personId); | ||||
|                 return person; | ||||
|                 return people.getPerson(personId); | ||||
|             } | ||||
|  | ||||
|             // TODO Do the sort in the query on day. A comment in the code for the V0 API used for live people | ||||
| @@ -341,28 +334,18 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|                 query.append("*\")"); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected List<Site> newList(int capacity) | ||||
|             { | ||||
|                 return new ArrayList<>(capacity); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             protected Site convert(NodeRef nodeRef, List<String> includeParam) | ||||
|             { | ||||
|                 return getSite(siteService.getSite(nodeRef), true); | ||||
|                 return getSite(siteService.getSite(nodeRef)); | ||||
|             } | ||||
|  | ||||
|             // note: see also Sites.getSite | ||||
|             private Site getSite(SiteInfo siteInfo, boolean includeRole) | ||||
|             private Site getSite(SiteInfo siteInfo) | ||||
|             { | ||||
|                 // set the site id to the short name (to deal with case sensitivity issues with using the siteId from the url) | ||||
|                 String siteId = siteInfo.getShortName(); | ||||
|                 String role = null; | ||||
|                 if (includeRole) | ||||
|                 { | ||||
|                     role = sites.getSiteRole(siteId); | ||||
|                 } | ||||
|                 String role = sites.getSiteRole(siteId); | ||||
|                 return new Site(siteInfo, role); | ||||
|             } | ||||
|         }.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_SITES, "_SITE", POST_QUERY_SORT, SITE_SORT_PARAMS_TO_QNAMES, new SortColumn(PARAM_SITE_TITLE, true)); | ||||
| @@ -412,34 +395,38 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|             } | ||||
|  | ||||
|             ResultSet queryResults = null; | ||||
|             List<T> collection = null; | ||||
|             try | ||||
|             { | ||||
|                 queryResults = searchService.query(sp); | ||||
|  | ||||
|                 List<NodeRef> nodeRefs = queryResults.getNodeRefs(); | ||||
|  | ||||
|                 if (sort == POST_QUERY_SORT) | ||||
|                 { | ||||
|                     nodeRefs = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, nodeRefs); | ||||
|                 } | ||||
|  | ||||
|                 collection = newList(nodeRefs.size()); | ||||
|                 Map<NodeRef, T> collection = new LinkedHashMap<>(nodeRefs.size()); | ||||
|                 List<String> includeParam = parameters.getInclude(); | ||||
|  | ||||
|                 for (NodeRef nodeRef : nodeRefs) | ||||
|                 { | ||||
|                     T t = convert(nodeRef, includeParam); | ||||
|                     collection.add(t); | ||||
|                     try | ||||
|                     { | ||||
|                         T t = convert(nodeRef, includeParam); | ||||
|                         collection.put(nodeRef, t); | ||||
|                     } | ||||
|                     catch (AccessDeniedException ade) | ||||
|                     { | ||||
|                         LOGGER.debug("Ignoring search result for nodeRef " + nodeRef + " due to access denied exception", ade); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (sort == POST_QUERY_SORT) | ||||
|                 { | ||||
|                     return listPage(collection, paging); | ||||
|                     List<T> postQuerySortedCollection = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, collection.keySet()) | ||||
|                             .stream() | ||||
|                             .map(collection::get) | ||||
|                             .toList(); | ||||
|                     return listPage(postQuerySortedCollection, paging); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     return CollectionWithPagingInfo.asPaged(paging, collection, queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue()); | ||||
|                     return CollectionWithPagingInfo.asPaged(paging, collection.values(), queryResults.hasMore(), Long.valueOf(queryResults.getNumberFound()).intValue()); | ||||
|                 } | ||||
|             } | ||||
|             finally | ||||
| @@ -464,15 +451,6 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|          */ | ||||
|         protected abstract void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName); | ||||
|  | ||||
|         /** | ||||
|          * Returns a list of the correct type. | ||||
|          *  | ||||
|          * @param capacity | ||||
|          *            of the list | ||||
|          * @return a new list. | ||||
|          */ | ||||
|         protected abstract List<T> newList(int capacity); | ||||
|  | ||||
|         /** | ||||
|          * Converts a nodeRef into the an object of the required type. | ||||
|          *  | ||||
| @@ -551,7 +529,7 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|         private List<SortColumn> getSorting(Parameters parameters, List<SortColumn> defaultSortCols) | ||||
|         { | ||||
|             List<SortColumn> sortCols = parameters.getSorting(); | ||||
|             if (sortCols == null || sortCols.size() == 0) | ||||
|             if (sortCols == null || sortCols.isEmpty()) | ||||
|             { | ||||
|                 sortCols = defaultSortCols == null ? Collections.emptyList() : defaultSortCols; | ||||
|             } | ||||
| @@ -559,62 +537,66 @@ public class QueriesImpl implements Queries, InitializingBean | ||||
|         } | ||||
|  | ||||
|         protected List<NodeRef> postQuerySort(Parameters parameters, Map<String, QName> sortParamsToQNames, | ||||
|                 List<SortColumn> defaultSortCols, List<NodeRef> nodeRefs) | ||||
|                 List<SortColumn> defaultSortCols, Set<NodeRef> unsortedNodeRefs) | ||||
|         { | ||||
|             final List<SortColumn> sortCols = getSorting(parameters, defaultSortCols); | ||||
|             int sortColCount = sortCols.size(); | ||||
|             if (sortColCount > 0) | ||||
|             { | ||||
|                 // make copy of nodeRefs because it can be unmodifiable list. | ||||
|                 nodeRefs = new ArrayList<NodeRef>(nodeRefs); | ||||
|  | ||||
|                 List<QName> sortPropQNames = new ArrayList<>(sortColCount); | ||||
|                 for (SortColumn sortCol : sortCols) | ||||
|             if (sortColCount == 0) | ||||
|             { | ||||
|                 return new ArrayList<>(unsortedNodeRefs); | ||||
|             } | ||||
|  | ||||
|             // make copy of nodeRefs because it can be unmodifiable list. | ||||
|             List<NodeRef> sortedNodeRefs = new ArrayList<>(unsortedNodeRefs); | ||||
|  | ||||
|             List<QName> sortPropQNames = new ArrayList<>(sortColCount); | ||||
|             for (SortColumn sortCol : sortCols) | ||||
|             { | ||||
|                 QName sortPropQName = sortParamsToQNames.get(sortCol.column); | ||||
|                 if (sortPropQName == null) | ||||
|                 { | ||||
|                     QName sortPropQName = sortParamsToQNames.get(sortCol.column); | ||||
|                     if (sortPropQName == null) | ||||
|                     throw new InvalidArgumentException("Invalid sort field: " + sortCol.column); | ||||
|                 } | ||||
|                 sortPropQNames.add(sortPropQName); | ||||
|             } | ||||
|  | ||||
|             final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale()); | ||||
|             Collections.sort(sortedNodeRefs, new Comparator<NodeRef>() { | ||||
|                 @Override | ||||
|                 public int compare(NodeRef n1, NodeRef n2) | ||||
|                 { | ||||
|                     int result = 0; | ||||
|                     for (int i = 0; i < sortCols.size(); i++) | ||||
|                     { | ||||
|                         throw new InvalidArgumentException("Invalid sort field: " + sortCol.column); | ||||
|                         SortColumn sortCol = sortCols.get(i); | ||||
|                         QName sortPropQName = sortPropQNames.get(i); | ||||
|  | ||||
|                         Serializable p1 = getProperty(n1, sortPropQName); | ||||
|                         Serializable p2 = getProperty(n2, sortPropQName); | ||||
|  | ||||
|                         result = ((p1 instanceof Long) && (p2 instanceof Long) | ||||
|                                 ? Long.compare((Long) p1, (Long) p2) | ||||
|                                 : col.compare(p1.toString(), p2.toString())) | ||||
|                                 * (sortCol.asc ? 1 : -1); | ||||
|  | ||||
|                         if (result != 0) | ||||
|                         { | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     sortPropQNames.add(sortPropQName); | ||||
|                     return result; | ||||
|                 } | ||||
|  | ||||
|                 final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale()); | ||||
|                 Collections.sort(nodeRefs, new Comparator<NodeRef>() { | ||||
|                     @Override | ||||
|                     public int compare(NodeRef n1, NodeRef n2) | ||||
|                     { | ||||
|                         int result = 0; | ||||
|                         for (int i = 0; i < sortCols.size(); i++) | ||||
|                         { | ||||
|                             SortColumn sortCol = sortCols.get(i); | ||||
|                             QName sortPropQName = sortPropQNames.get(i); | ||||
|                 private Serializable getProperty(NodeRef nodeRef, QName sortPropQName) | ||||
|                 { | ||||
|                     Serializable result = nodeService.getProperty(nodeRef, sortPropQName); | ||||
|                     return result == null ? "" : result; | ||||
|                 } | ||||
|  | ||||
|                             Serializable p1 = getProperty(n1, sortPropQName); | ||||
|                             Serializable p2 = getProperty(n2, sortPropQName); | ||||
|             }); | ||||
|  | ||||
|                             result = ((p1 instanceof Long) && (p2 instanceof Long) | ||||
|                                     ? Long.compare((Long) p1, (Long) p2) | ||||
|                                     : col.compare(p1.toString(), p2.toString())) | ||||
|                                     * (sortCol.asc ? 1 : -1); | ||||
|  | ||||
|                             if (result != 0) | ||||
|                             { | ||||
|                                 break; | ||||
|                             } | ||||
|                         } | ||||
|                         return result; | ||||
|                     } | ||||
|  | ||||
|                     private Serializable getProperty(NodeRef nodeRef, QName sortPropQName) | ||||
|                     { | ||||
|                         Serializable result = nodeService.getProperty(nodeRef, sortPropQName); | ||||
|                         return result == null ? "" : result; | ||||
|                     } | ||||
|  | ||||
|                 }); | ||||
|             } | ||||
|             return nodeRefs; | ||||
|             return sortedNodeRefs; | ||||
|         } | ||||
|  | ||||
|         // note: see also AbstractNodeRelation | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Remote API | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -75,6 +75,7 @@ public class ActionNodeParameterValidator implements ActionValidator | ||||
|     static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: "; | ||||
|     static final String NOT_A_CATEGORY = "Node is not a category "; | ||||
|     static final String NOT_A_FOLDER = "Node is not a folder "; | ||||
|     static final String NO_LONGER_EXISTS = "%s having Id: %s no longer exists. Please update your rule definition."; | ||||
|  | ||||
|     private final Actions actions; | ||||
|     private final NamespaceService namespaceService; | ||||
| @@ -132,7 +133,15 @@ public class ActionNodeParameterValidator implements ActionValidator | ||||
|                     .filter(pd -> action.getParams().containsKey(pd.getName())) | ||||
|                     .forEach(p -> { | ||||
|                         final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY); | ||||
|                         final NodeRef nodeRef = nodes.validateNode(nodeId); | ||||
|                         NodeRef nodeRef; | ||||
|                         try | ||||
|                         { | ||||
|                             nodeRef = nodes.validateNode(nodeId); | ||||
|                         } | ||||
|                         catch (EntityNotFoundException e) | ||||
|                         { | ||||
|                             throw new EntityNotFoundException(String.format(NO_LONGER_EXISTS, p.getDisplayLabel(), nodeId), e); | ||||
|                         } | ||||
|                         validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef); | ||||
|                         validateType(action.getActionDefinitionId(), nodeRef); | ||||
|                     }); | ||||
| @@ -169,4 +178,5 @@ public class ActionNodeParameterValidator implements ActionValidator | ||||
|             throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Admin Console | ||||
| admin-console.help=Help | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Successfully saved values. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Konzole pro spr\u00e1vce | ||||
| admin-console.help=N\u00e1pov\u011bda | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Hodnoty byly \u00fasp\u011b\u0161n\u011b ulo\u017eeny. | ||||
|  | ||||
| admin-console.host=Hostitel | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Administrationskonsol | ||||
| admin-console.help=Hj\u00e6lp | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=V\u00e6rdierne blev gemt. | ||||
|  | ||||
| admin-console.host=V\u00e6rt | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Administratorkonsole | ||||
| admin-console.help=Hilfe | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Erfolgreich gespeicherte Werte. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Consola de administraci\u00f3n | ||||
| admin-console.help=Ayuda | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Valores guardados correctamente. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Hallintakonsoli | ||||
| admin-console.help=Ohje | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Arvot tallennettiin. | ||||
|  | ||||
| admin-console.host=Is\u00e4nt\u00e4 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Console d'administration | ||||
| admin-console.help=Aide | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Les valeurs ont bien \u00e9t\u00e9 enregistr\u00e9es. | ||||
|  | ||||
| admin-console.host=H\u00f4te | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Console di amministrazione | ||||
| admin-console.help=Aiuto | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=I valori sono stati salvati. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb | ||||
| admin-console.help=\u30d8\u30eb\u30d7 | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=\u5024\u3092\u6b63\u5e38\u306b\u4fdd\u5b58\u3057\u307e\u3057\u305f\u3002 | ||||
|  | ||||
| admin-console.host=\u30db\u30b9\u30c8 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Admin-konsoll | ||||
| admin-console.help=Hjelp | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Verdier som ble lagret. | ||||
|  | ||||
| admin-console.host=Vert | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Beheerconsole | ||||
| admin-console.help=Help | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Waarden zijn opgeslagen. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Konsola administracyjna | ||||
| admin-console.help=Pomoc | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Warto\u015bci zosta\u0142y zapisane pomy\u015blnie. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Console de administra\u00e7\u00e3o | ||||
| admin-console.help=Ajuda | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=Valores salvos com sucesso. | ||||
|  | ||||
| admin-console.host=Host | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=\u041a\u043e\u043d\u0441\u043e\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 | ||||
| admin-console.help=\u0421\u043f\u0440\u0430\u0432\u043a\u0430 | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. | ||||
|  | ||||
| admin-console.host=\u0425\u043e\u0441\u0442 | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=Admin-konsol | ||||
| admin-console.help=Hj\u00e4lp | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=V\u00e4rden sparades. | ||||
|  | ||||
| admin-console.host=V\u00e4rd | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # I18N messages for the Repository Admin Console | ||||
| admin-console.header=\u7ba1\u7406\u63a7\u5236\u53f0 | ||||
| admin-console.help=\u5e2e\u52a9 | ||||
| admin-console.help-link=https://support.hyland.com/p/alfresco | ||||
| admin-console.help-link-topic=qvs1720602310678 | ||||
| admin-console.success=\u5df2\u6210\u529f\u4fdd\u5b58\u7684\u503c\u3002 | ||||
|  | ||||
| admin-console.host=\u4e3b\u673a | ||||
|   | ||||
| @@ -5,4 +5,4 @@ | ||||
|    <authentication>guest</authentication> | ||||
|    <transaction allow="readonly">required</transaction> | ||||
|    <lifecycle>internal</lifecycle> | ||||
| </webscript> | ||||
| </webscript> | ||||
|   | ||||
| @@ -554,7 +554,7 @@ Admin.addEventListener(window, 'load', function() { | ||||
|  | ||||
|       <div class="header"> | ||||
|          <span><a href="${url.serviceContext}${DEFAULT_CONTROLLER!"/admin"}">${msg("admin-console.header")}</a></span><#if metadata??><span class="meta">${HOSTNAME}</span><span class="meta">${HOSTADDR}</span></#if> | ||||
|          <div style="float:right"><a href="${msg("admin-console.help-link", docsEdition)}" target="_blank">${msg("admin-console.help")}</a></div> | ||||
|          <div style="float:right"><a href="${documentationUrl(msg("admin-console.help-link-topic"),"&component=Alfresco%20Content%20Services")}" target="_blank">${msg("admin-console.help")}</a></div> | ||||
|       </div> | ||||
|        | ||||
|       <div class="navigation-wrapper"> | ||||
|   | ||||
| @@ -214,9 +214,13 @@ | ||||
|       <property name="authenticationListener" ref="webScriptAuthenticationListener"/> | ||||
|       <property name="remoteUserMapper" ref="RemoteUserMapper" /> | ||||
|       <property name="adminConsoleAuthenticator" ref="AdminConsoleAuthenticator" /> | ||||
|        <property name="webScriptsHomeAuthenticator" ref="WebScriptsHomeAuthenticator" /> | ||||
|       <property name="alwaysAllowBasicAuthForAdminConsole"> | ||||
|          <value>${authentication.alwaysAllowBasicAuthForAdminConsole.enabled}</value> | ||||
|       </property> | ||||
|        <property name="alwaysAllowBasicAuthForWebScriptsHome"> | ||||
|            <value>${authentication.alwaysAllowBasicAuthForWebScriptsHome.enabled}</value> | ||||
|        </property> | ||||
|       <property name="getRemoteUserTimeoutMilliseconds"> | ||||
|          <value>${authentication.getRemoteUserTimeoutMilliseconds}</value> | ||||
|       </property> | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertTrue; | ||||
| import static org.junit.Assert.fail; | ||||
| import static org.mockito.Mockito.lenient; | ||||
| import static org.mockito.Mockito.never; | ||||
| import static org.mockito.Mockito.verify; | ||||
| import static org.mockito.Mockito.when; | ||||
| @@ -203,8 +204,8 @@ public class MoveMethodTest | ||||
|     @Test | ||||
|     public void canRenameFoldersWhenNewNameMatchesShufflePattern() throws Exception | ||||
|     { | ||||
|         when(davHelper.isRenameShuffle(destPath)).thenReturn(true); | ||||
|         when(davHelper.isRenameShuffle(sourcePath)).thenReturn(false); | ||||
|         lenient().when(davHelper.isRenameShuffle(destPath)).thenReturn(true); | ||||
|         lenient().when(davHelper.isRenameShuffle(sourcePath)).thenReturn(false); | ||||
|  | ||||
|         // Test: Perform the rename | ||||
|         moveMethod.moveOrCopy(sourceNodeRef, sourceParentNodeRef, destParentNodeRef, "dest.doc"); | ||||
| @@ -247,8 +248,8 @@ public class MoveMethodTest | ||||
|         sourcePath = "/path/from/test.doc"; | ||||
|         moveMethod.m_strPath = sourcePath; | ||||
|  | ||||
|         when(davHelper.getServiceRegistry()).thenReturn(mockServiceRegistry); | ||||
|         when(mockServiceRegistry.getContentService()).thenReturn(mockContentService); | ||||
|         lenient().when(davHelper.getServiceRegistry()).thenReturn(mockServiceRegistry); | ||||
|         lenient().when(mockServiceRegistry.getContentService()).thenReturn(mockContentService); | ||||
|  | ||||
|         List<String> sourcePathSplit = Arrays.asList("path", "from", "test.doc"); | ||||
|         when(davHelper.splitAllPaths(sourcePath)).thenReturn(sourcePathSplit); | ||||
| @@ -366,7 +367,7 @@ public class MoveMethodTest | ||||
|  | ||||
|                     when(mockFileFolderService.resolveNamePath(rootNode, sourcePathSplit)).thenReturn(tmpFI); | ||||
|                     when(davHelper.isRenameShuffle(destPath)).thenReturn(false); | ||||
|                     when(davHelper.isRenameShuffle(sourcePath)).thenReturn(true); | ||||
|                     lenient().when(davHelper.isRenameShuffle(sourcePath)).thenReturn(true); | ||||
|  | ||||
|                     moveMethod.moveOrCopy(atmpFI.getNodeRef(), companyHomeNodeRef, companyHomeNodeRef, bakFileName); | ||||
|  | ||||
|   | ||||
| @@ -130,6 +130,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest | ||||
|     public void testLiveSearchSites() throws Exception | ||||
|     { | ||||
|         setRequestContext(user1); | ||||
|         AuthenticationUtil.setFullyAuthenticatedUser(user1); | ||||
|  | ||||
|         int sCount = 5; | ||||
|         assertTrue(sCount > 4); // as relied on by test below | ||||
| @@ -231,7 +232,11 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest | ||||
|  | ||||
|     private NodeRef getNodeRef(String createdSiteId) | ||||
|     { | ||||
|         AuthenticationUtil.setFullyAuthenticatedUser(user1); | ||||
|         // Created sites do not return NodeRefs to the caller so we need to get the NodeRef from the siteService. | ||||
|         // Temporarily as admin we will get NodeRefs to handle ACL authorization. | ||||
|         String userUnderTest = AuthenticationUtil.getFullyAuthenticatedUser(); | ||||
|         AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN); | ||||
|  | ||||
|         // The following call to siteService.getSite(createdSiteId).getNodeRef() returns a NodeRef like: | ||||
|         // workspace://SpacesStore/9db76769-96de-4de4-bdb4-a127130af362 | ||||
|         // We call tenantService.getName(nodeRef) to get a fully qualified NodeRef as Solr returns this. | ||||
| @@ -239,6 +244,8 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest | ||||
|         // workspace://@org.alfresco.rest.api.tests.queriespeopleapitest@SpacesStore/9db76769-96de-4de4-bdb4-a127130af362 | ||||
|         NodeRef nodeRef = siteService.getSite(createdSiteId).getNodeRef(); | ||||
|         nodeRef = tenantService.getName(nodeRef); | ||||
|  | ||||
|         AuthenticationUtil.setFullyAuthenticatedUser(userUnderTest); | ||||
|         return nodeRef; | ||||
|     } | ||||
|  | ||||
| @@ -246,6 +253,7 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest | ||||
|     public void testLiveSearchSites_SortPage() throws Exception | ||||
|     { | ||||
|         setRequestContext(user1); | ||||
|         AuthenticationUtil.setFullyAuthenticatedUser(user1); | ||||
|  | ||||
|         List<String> siteIds = new ArrayList<>(5); | ||||
|  | ||||
| @@ -306,6 +314,51 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If the search service do not support ACL filtering, then the Queries API should handle the response to exclude private sites and potential unauthorized error when building response. | ||||
|      */ | ||||
|     @Test | ||||
|     public void testLiveSearchExcludesPrivateSites() throws Exception | ||||
|     { | ||||
|         String publicSiteId = null; | ||||
|         String privateSiteId = null; | ||||
|         try | ||||
|         { | ||||
|             // given | ||||
|             setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD); | ||||
|             createUser("bartender"); | ||||
|  | ||||
|             publicSiteId = createSite("samePrefixPublicSite", "samePrefixPublicSite", "Visible to all users", SiteVisibility.PUBLIC, 201).getId(); | ||||
|             privateSiteId = createSite("samePrefixPrivateSite", "samePrefixPrivateSite", "Hidden from bartender", SiteVisibility.PRIVATE, 201).getId(); | ||||
|  | ||||
|             String[] searchResults = {publicSiteId, privateSiteId}; | ||||
|             String[] expectedSites = {publicSiteId}; | ||||
|  | ||||
|             // when | ||||
|             setRequestContext(null, "bartender", "password"); | ||||
|             AuthenticationUtil.setFullyAuthenticatedUser("bartender"); | ||||
|  | ||||
|             // then | ||||
|             checkApiCall("samePrefix", null, getPaging(0, 100), 200, expectedSites, searchResults); | ||||
|         } | ||||
|         finally | ||||
|         { | ||||
|             // cleanup | ||||
|             AuthenticationUtil.setFullyAuthenticatedUser(DEFAULT_ADMIN); | ||||
|             setRequestContext(null, DEFAULT_ADMIN, DEFAULT_ADMIN_PWD); | ||||
|             if (publicSiteId != null) | ||||
|             { | ||||
|                 deleteSite(publicSiteId, true, 204); | ||||
|             } | ||||
|             if (privateSiteId != null) | ||||
|             { | ||||
|                 deleteSite(privateSiteId, true, 204); | ||||
|             } | ||||
|             deleteUser("bartender", null); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getScope() | ||||
|     { | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -27,7 +27,7 @@ to integrate with a number of external Authentication providers including | ||||
|   * https://github.com/Alfresco/alfresco-data-model/tree/master/src/main/java/org/alfresco/repo/security/authentication | ||||
| * License: LGPL | ||||
| * Issue Tracker Link: https://issues.alfresco.com/jira/issues/?jql=project%3DREPO | ||||
| * Documentation Link: https://support.hyland.com/r/Alfresco/Alfresco-Content-Services-Community-Edition/23.4/Alfresco-Content-Services-Community-Edition/Administer/Manage-Security/Authentication-and-sync | ||||
| * Documentation Link: https://support.hyland.com/access?dita:id=byj1720776091160&vrm_version=25.2&component=Alfresco%20Content%20Services%20Community%20Edition | ||||
| * Contribution Model: Alfresco Open Source | ||||
| *** | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
| * Source Code Link:m https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/ | ||||
| * License: LGPL | ||||
| * Issue Tracker Link: https://issues.alfresco.com/jira/secure/RapidBoard.jspa?projectKey=REPO&useStoredSettings=true&rapidView=379 | ||||
| * Documentation Link: https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Configure/Repository/About-Versioning | ||||
| * Documentation Link: https://support.hyland.com/access?dita:id=ybx1720084724583&vrm_version=25.2 | ||||
| * Contribution Model: Alfresco publishes the source code and will review proposed patch requests | ||||
| *** | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.27</version> | ||||
|         <version>25.2.0.52-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -627,11 +627,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.assertj</groupId> | ||||
|             <artifactId>assertj-core</artifactId> | ||||
|   | ||||
| @@ -58,6 +58,7 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition; | ||||
| import org.alfresco.service.cmr.model.FileExistsException; | ||||
| import org.alfresco.service.cmr.model.FileFolderService; | ||||
| import org.alfresco.service.cmr.model.FileInfo; | ||||
| import org.alfresco.service.cmr.model.FolderExistsException; | ||||
| import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentService; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| @@ -366,7 +367,11 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase | ||||
|             catch (FileExistsException e) | ||||
|             { | ||||
|                 // TODO: add failed file info to status message? | ||||
|                 throw new AlfrescoRuntimeException("Failed to process ZIP file.", e); | ||||
|                 if (e.getType().equalsIgnoreCase("folder")) | ||||
|                 { | ||||
|                     throw new FolderExistsException(root, file.getName()); | ||||
|                 } | ||||
|                 throw e; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2019 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2019 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -39,6 +39,7 @@ import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| import org.alfresco.service.cmr.repository.MimetypeService; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.transform.config.TransformOption; | ||||
| import org.alfresco.transform.config.TransformOptionGroup; | ||||
| import org.alfresco.transform.config.TransformOptionValue; | ||||
| @@ -52,6 +53,7 @@ public abstract class AbstractLocalTransform implements LocalTransform | ||||
|  | ||||
|     protected final String name; | ||||
|     protected final MimetypeService mimetypeService; | ||||
|     protected final NodeService nodeService; | ||||
|     protected final TransformerDebug transformerDebug; | ||||
|  | ||||
|     protected final Set<String> transformsTransformOptionNames = new HashSet<>(); | ||||
| @@ -65,7 +67,8 @@ public abstract class AbstractLocalTransform implements LocalTransform | ||||
|             MimetypeService mimetypeService, boolean strictMimeTypeCheck, | ||||
|             Map<String, Set<String>> strictMimetypeExceptions, boolean retryTransformOnDifferentMimeType, | ||||
|             Set<TransformOption> transformsTransformOptions, | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry) | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry, | ||||
|             NodeService nodeService) | ||||
|     { | ||||
|         this.name = name; | ||||
|         this.transformerDebug = transformerDebug; | ||||
| @@ -74,6 +77,7 @@ public abstract class AbstractLocalTransform implements LocalTransform | ||||
|         this.strictMimetypeExceptions = strictMimetypeExceptions; | ||||
|         this.retryTransformOnDifferentMimeType = retryTransformOnDifferentMimeType; | ||||
|         this.localTransformServiceRegistry = localTransformServiceRegistry; | ||||
|         this.nodeService = nodeService; | ||||
|  | ||||
|         addOptionNames(transformsTransformOptionNames, transformsTransformOptions); | ||||
|     } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2019 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2019 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -37,6 +37,7 @@ import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| import org.alfresco.service.cmr.repository.MimetypeService; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.transform.config.TransformOption; | ||||
| import org.alfresco.util.TempFileProvider; | ||||
|  | ||||
| @@ -54,10 +55,10 @@ public class LocalFailoverTransform extends AbstractLocalTransform | ||||
|             Map<String, Set<String>> strictMimetypeExceptions, | ||||
|             boolean retryTransformOnDifferentMimeType, | ||||
|             Set<TransformOption> transformsTransformOptions, | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry) | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry, NodeService nodeService) | ||||
|     { | ||||
|         super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry, nodeService); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -41,6 +41,7 @@ import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| import org.alfresco.service.cmr.repository.MimetypeService; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.transform.config.SupportedSourceAndTarget; | ||||
| import org.alfresco.transform.config.TransformOption; | ||||
| import org.alfresco.transform.config.Transformer; | ||||
| @@ -63,10 +64,10 @@ public class LocalPassThroughTransform extends AbstractLocalTransform | ||||
|             Map<String, Set<String>> strictMimetypeExceptions, | ||||
|             boolean retryTransformOnDifferentMimeType, | ||||
|             Set<TransformOption> transformsTransformOptions, | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry) | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry, NodeService nodeService) | ||||
|     { | ||||
|         super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry, nodeService); | ||||
|     } | ||||
|  | ||||
|     public static Transformer getConfig(List<String> mimetypes) | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -38,6 +38,7 @@ import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| import org.alfresco.service.cmr.repository.MimetypeService; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.transform.config.TransformOption; | ||||
| import org.alfresco.util.TempFileProvider; | ||||
|  | ||||
| @@ -61,10 +62,10 @@ public class LocalPipelineTransform extends AbstractLocalTransform | ||||
|             Map<String, Set<String>> strictMimetypeExceptions, | ||||
|             boolean retryTransformOnDifferentMimeType, | ||||
|             Set<TransformOption> transformsTransformOptions, | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry) | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry, NodeService nodeService) | ||||
|     { | ||||
|         super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry, nodeService); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -26,19 +26,24 @@ | ||||
| package org.alfresco.repo.content.transform; | ||||
|  | ||||
| import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING; | ||||
| import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_FILENAME; | ||||
| import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_NODE_REF; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
|  | ||||
| import org.alfresco.httpclient.HttpClientConfig; | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.repo.content.metadata.AsynchronousExtractor; | ||||
| import org.alfresco.repo.rendition2.RenditionDefinition2; | ||||
| import org.alfresco.service.cmr.repository.ContentReader; | ||||
| import org.alfresco.service.cmr.repository.ContentWriter; | ||||
| import org.alfresco.service.cmr.repository.MimetypeService; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.transform.config.TransformOption; | ||||
| import org.alfresco.util.Pair; | ||||
|  | ||||
| @@ -60,10 +65,11 @@ public class LocalTransformImpl extends AbstractLocalTransform | ||||
|             Set<TransformOption> transformsTransformOptions, | ||||
|             LocalTransformServiceRegistry localTransformServiceRegistry, String baseUrl, | ||||
|             HttpClientConfig httpClientConfig, | ||||
|             NodeService nodeService, | ||||
|             int startupRetryPeriodSeconds) | ||||
|     { | ||||
|         super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions, | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry); | ||||
|                 retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry, nodeService); | ||||
|         remoteTransformerClient = new RemoteTransformerClient(name, baseUrl, httpClientConfig); | ||||
|         remoteTransformerClient.setStartupRetryPeriodSeconds(startupRetryPeriodSeconds); | ||||
|  | ||||
| @@ -155,6 +161,17 @@ public class LocalTransformImpl extends AbstractLocalTransform | ||||
|             transformOptions.put(SOURCE_NODE_REF, sourceNodeRef.toString()); | ||||
|         } | ||||
|  | ||||
|         String filename = null; | ||||
|         if (sourceNodeRef != null && nodeService.exists(sourceNodeRef)) | ||||
|         { | ||||
|             filename = (String) nodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME); | ||||
|         } | ||||
|  | ||||
|         if (StringUtils.isNotEmpty(filename)) | ||||
|         { | ||||
|             transformOptions.put(SOURCE_FILENAME, filename); | ||||
|         } | ||||
|  | ||||
|         // Build an array of option names and values and extract the timeout. | ||||
|         long timeoutMs = 0; | ||||
|         int nonOptions = transformOptions.containsKey(RenditionDefinition2.TIMEOUT) ? 1 : 0; | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user