mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			25.3.0.46
			...
			feature/AC
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 3b77e4f2a3 | ||
|  | d3e78b4705 | ||
|  | f93213d342 | 
							
								
								
									
										79
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										79
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,6 +15,7 @@ on: | ||||
|   workflow_dispatch: | ||||
|  | ||||
| env: | ||||
|   JAVA_VERSION: '21' | ||||
|   DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} | ||||
|   DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }} | ||||
|   GITHUB_ACTIONS_DEPLOY_TIMEOUT: 60 | ||||
| @@ -38,12 +39,14 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v8.24.1 | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
| @@ -61,10 +64,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v8.24.1 | ||||
| @@ -84,10 +89,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v8.24.1 | ||||
|         with: | ||||
|           token: ${{ secrets.BOT_GITHUB_TOKEN }} | ||||
| @@ -144,6 +151,8 @@ jobs: | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - uses: Alfresco/ya-pmd-scan@v4.3.0 | ||||
|         with: | ||||
|           classpath-build-command: "mvn test-compile -ntp -Pags -pl \"-:alfresco-community-repo-docker\"" | ||||
| @@ -173,10 +182,12 @@ jobs: | ||||
|             testModule: mmt | ||||
|             testAttributes: "-Dtest=AllMmtUnitTestSuite" | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run tests" | ||||
| @@ -210,10 +221,12 @@ jobs: | ||||
|     env: | ||||
|       REQUIRES_INSTALLED_ARTIFACTS: true | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
| @@ -245,10 +258,12 @@ jobs: | ||||
|       matrix: | ||||
|         version: ['10.5', '10.6'] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: Run MariaDB ${{ matrix.version }} database | ||||
| @@ -272,10 +287,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run MariaDB 10.11 database" | ||||
| @@ -299,10 +316,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run MySQL 8 database" | ||||
| @@ -325,10 +344,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run PostgreSQL 14.15 database" | ||||
| @@ -351,10 +372,12 @@ jobs: | ||||
|             !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|             !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run PostgreSQL 15.10 database" | ||||
| @@ -377,10 +400,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run PostgreSQL 16.6 database" | ||||
| @@ -401,10 +426,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run ActiveMQ" | ||||
| @@ -457,10 +484,12 @@ jobs: | ||||
|             disabledHostnameVerification: false | ||||
|             mvn-options: '-Dencryption.ssl.keystore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.keystore -Dencryption.ssl.truststore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.truststore' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Set transformers tag" | ||||
| @@ -527,10 +556,12 @@ jobs: | ||||
|     env: | ||||
|       REQUIRES_LOCAL_IMAGES: true | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
| @@ -566,10 +597,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - name: "Run Postgres 16.6 database" | ||||
| @@ -596,10 +629,12 @@ jobs: | ||||
|     env: | ||||
|       REQUIRES_INSTALLED_ARTIFACTS: true | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
| @@ -628,10 +663,12 @@ jobs: | ||||
|     env: | ||||
|       REQUIRES_INSTALLED_ARTIFACTS: true | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
| @@ -656,10 +693,12 @@ jobs: | ||||
|     env: | ||||
|       REQUIRES_LOCAL_IMAGES: true | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
| @@ -702,10 +741,12 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[skip tests]') && | ||||
|       !contains(github.event.head_commit.message, '[force]') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Build" | ||||
|         timeout-minutes: ${{ fromJSON(env.GITHUB_ACTIONS_DEPLOY_TIMEOUT) }} | ||||
|         run: | | ||||
|   | ||||
							
								
								
									
										9
									
								
								.github/workflows/master_release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/master_release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -7,6 +7,7 @@ on: | ||||
|       - release/** | ||||
|  | ||||
| env: | ||||
|   JAVA_VERSION: '21' | ||||
|   GIT_USERNAME: ${{ secrets.BOT_GITHUB_USERNAME }} | ||||
|   GIT_EMAIL: ${{ secrets.BOT_GITHUB_EMAIL }} | ||||
|   GIT_PASSWORD: ${{ secrets.BOT_GITHUB_TOKEN }} | ||||
| @@ -31,12 +32,14 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[no release]') && | ||||
|       github.event_name != 'pull_request' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|         with: | ||||
|           persist-credentials: false | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.24.1 | ||||
| @@ -60,12 +63,14 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[no downstream]') && | ||||
|       github.event_name != 'pull_request' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|         with: | ||||
|           persist-credentials: false | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.24.1 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.24.1 | ||||
|         with: | ||||
|           java-version: ${{ env.JAVA_VERSION }} | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.24.1 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/precommit_formatter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/precommit_formatter.yml
									
									
									
									
										vendored
									
									
								
							| @@ -11,7 +11,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     if: contains(github.event.head_commit.message, '[reformat code]') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v5 | ||||
|       - uses: actions/checkout@v4 | ||||
|       - name: Set up Python ${{ inputs.python-version }} | ||||
|         uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | ||||
|         with: | ||||
|   | ||||
| @@ -133,7 +133,7 @@ | ||||
|         "filename": ".github/workflows/master_release.yml", | ||||
|         "hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0", | ||||
|         "is_verified": false, | ||||
|         "line_number": 24, | ||||
|         "line_number": 25, | ||||
|         "is_secret": false | ||||
|       } | ||||
|     ], | ||||
| @@ -1242,7 +1242,7 @@ | ||||
|         "filename": "repository/src/main/resources/alfresco/repository.properties", | ||||
|         "hashed_secret": "1459a56410378e4d3ab470eff570e5eae1742762", | ||||
|         "is_verified": false, | ||||
|         "line_number": 314, | ||||
|         "line_number": 312, | ||||
|         "is_secret": false | ||||
|       }, | ||||
|       { | ||||
| @@ -1250,7 +1250,7 @@ | ||||
|         "filename": "repository/src/main/resources/alfresco/repository.properties", | ||||
|         "hashed_secret": "84551ae5442affc9f1a2d3b4c86ae8b24860149d", | ||||
|         "is_verified": false, | ||||
|         "line_number": 773, | ||||
|         "line_number": 771, | ||||
|         "is_secret": false | ||||
|       } | ||||
|     ], | ||||
| @@ -1845,5 +1845,5 @@ | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "generated_at": "2025-07-23T08:25:11Z" | ||||
|   "generated_at": "2025-09-04T08:27:43Z" | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-automation-community-repo</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <build> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -15,13 +15,6 @@ | ||||
|       <parameter property="end" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|    </parameterMap> | ||||
|  | ||||
|    <parameterMap id="parameter_NodeIdsWhichReferenceContentUrl" type="map"> | ||||
|       <parameter property="contentUrlShort" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|       <parameter property="contentUrlCrc" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|       <parameter property="localName" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|       <parameter property="uri" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|    </parameterMap> | ||||
|  | ||||
|    <resultMap id="result_NodeRefEntity" type="org.alfresco.module.org_alfresco_module_rm.query.NodeRefEntity"> | ||||
|       <result property="row" column="row" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|       <result property="protocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
| @@ -62,21 +55,18 @@ | ||||
|  | ||||
|    <!-- Get list of node ids which reference given content url --> | ||||
|    <select id="select_NodeIdsWhichReferenceContentUrl" | ||||
|            parameterMap="parameter_NodeIdsWhichReferenceContentUrl" | ||||
|            parameterType="ContentUrl" | ||||
|            resultMap="result_NodeIds"> | ||||
|       select | ||||
|          p.node_id | ||||
|       from | ||||
|          alf_content_url cu | ||||
|          left outer join alf_content_data cd ON (cd.content_url_id = cu.id) | ||||
|          left outer join alf_node_properties p ON (p.long_value = cd.id) | ||||
|          left outer join alf_qname q ON (q.id = p.qname_id) | ||||
|          left outer join alf_namespace n ON (n.id = q.ns_id) | ||||
|       where | ||||
|          cu.content_url_short = ? and | ||||
|          cu.content_url_crc = ? and | ||||
|          q.local_name = ? and | ||||
|          n.uri = ? | ||||
|       LEFT OUTER JOIN alf_content_data cd ON (cd.content_url_id = cu.id) | ||||
|       LEFT OUTER JOIN alf_node_properties p ON (p.long_value = cd.id) | ||||
|       WHERE | ||||
|          content_url_short = #{contentUrlShort} and | ||||
|          content_url_crc = #{contentUrlCrc} | ||||
|  | ||||
|    </select> | ||||
|  | ||||
|    <select id="select_RecordFoldersWithSchedules" | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <properties> | ||||
|   | ||||
| @@ -39,7 +39,6 @@ import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.mybatis.spring.SqlSessionTemplate; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; | ||||
| import org.alfresco.repo.domain.contentdata.ContentUrlEntity; | ||||
| import org.alfresco.repo.domain.node.NodeDAO; | ||||
| @@ -192,19 +191,13 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, | ||||
|         ContentUrlEntity contentUrlEntity = new ContentUrlEntity(); | ||||
|         contentUrlEntity.setContentUrl(contentUrl.toLowerCase()); | ||||
|  | ||||
|         Map<String, Object> params = new HashMap<>(4); | ||||
|         params.put("contentUrlShort", contentUrlEntity.getContentUrlShort()); | ||||
|         params.put("contentUrlCrc", contentUrlEntity.getContentUrlCrc()); | ||||
|         params.put("localName", ContentModel.PROP_CONTENT.getLocalName()); | ||||
|         params.put("uri", ContentModel.PROP_CONTENT.getNamespaceURI()); | ||||
|  | ||||
|         if (logger.isDebugEnabled()) | ||||
|         { | ||||
|             logger.debug("Executing query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL); | ||||
|         } | ||||
|  | ||||
|         // Get all the node ids which reference the given content url | ||||
|         List<Long> nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, params); | ||||
|         List<Long> nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, contentUrlEntity); | ||||
|  | ||||
|         if (logger.isDebugEnabled()) | ||||
|         { | ||||
|   | ||||
| @@ -36,7 +36,6 @@ import java.util.Set; | ||||
|  | ||||
| import org.springframework.context.ApplicationListener; | ||||
| import org.springframework.context.event.ContextRefreshedEvent; | ||||
| import org.springframework.dao.ConcurrencyFailureException; | ||||
| import org.springframework.extensions.webscripts.ui.common.StringUtils; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| @@ -650,8 +649,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|         } | ||||
|         catch (DuplicateChildNodeNameException ex) | ||||
|         { | ||||
|             // Rethrow as ConcurrencyFailureException so that is can be retried and linked to the group created by the concurrent transaction | ||||
|             throw new ConcurrencyFailureException("IPR group creation failed due to concurrent duplicate group name creation: " + groupShortName); | ||||
|             // the group was concurrently created | ||||
|             group = authorityService.getName(AuthorityType.GROUP, groupShortName); | ||||
|         } | ||||
|  | ||||
|         return group; | ||||
|   | ||||
| @@ -29,23 +29,14 @@ package org.alfresco.module.org_alfresco_module_rm.test.legacy.service; | ||||
|  | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| import org.junit.Assert; | ||||
| import org.springframework.dao.ConcurrencyFailureException; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; | ||||
| import org.alfresco.query.PagingRequest; | ||||
| import org.alfresco.query.PagingResults; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationUtil; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; | ||||
| import org.alfresco.repo.site.SiteModel; | ||||
| import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.security.AccessPermission; | ||||
| import org.alfresco.service.cmr.security.AccessStatus; | ||||
| import org.alfresco.service.cmr.security.AuthorityType; | ||||
| import org.alfresco.service.cmr.site.SiteService; | ||||
| import org.alfresco.service.cmr.site.SiteVisibility; | ||||
| import org.alfresco.util.GUID; | ||||
| @@ -215,8 +206,7 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase | ||||
|         final NodeRef record = doTestInTransaction(new Test<NodeRef>() { | ||||
|             public NodeRef run() throws Exception | ||||
|             { | ||||
|                 NodeRef record = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_CONTENT) | ||||
|                         .getNodeRef(); | ||||
|                 NodeRef record = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef(); | ||||
|                 recordService.createRecord(filePlan, record); | ||||
|                 return record; | ||||
|             } | ||||
| @@ -289,238 +279,4 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public void testConcurrentSetWithRetry() | ||||
|     { | ||||
|         Set<String> extendedReaders = new HashSet<>(2); | ||||
|         Set<String> extendedWriters = new HashSet<>(2); | ||||
|  | ||||
|         Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters); | ||||
|  | ||||
|         // For each record created previously, spawn a thread to set extended security so we cause concurrency | ||||
|         // failure trying to create IPR groups with the same name | ||||
|         fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, true); | ||||
|  | ||||
|         // Look for duplicated IPR groups and verify all documents have the same groups assigned | ||||
|         verifyCreatedGroups(documents, false); | ||||
|  | ||||
|         AuthenticationUtil.clearCurrentSecurityContext(); | ||||
|     } | ||||
|  | ||||
|     public void testConcurrentSetWithoutRetry() | ||||
|     { | ||||
|         Set<String> extendedReaders = new HashSet<>(2); | ||||
|         Set<String> extendedWriters = new HashSet<>(2); | ||||
|  | ||||
|         Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters); | ||||
|  | ||||
|         // For each record created previously, spawn a thread to set extended security so we cause concurrency | ||||
|         // failure trying to create IPR groups with the same name. | ||||
|         // Since there is no retry, we expect to get a ConcurrencyFailureException | ||||
|         Assert.assertThrows(ConcurrencyFailureException.class, () -> { | ||||
|             fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, false); | ||||
|         }); | ||||
|  | ||||
|         // Look for duplicated IPR groups and verify all documents have the same groups assigned | ||||
|         // Since there was a ConcurrencyFailureException some threads failed to set extended security so some | ||||
|         // documents may not have IPR groups created. | ||||
|         verifyCreatedGroups(documents, true); | ||||
|  | ||||
|         AuthenticationUtil.clearCurrentSecurityContext(); | ||||
|     } | ||||
|  | ||||
|     private Set<NodeRef> setupConcurrentTestCase(int concurrentThreads, Set<String> extendedReaders, Set<String> extendedWriters) | ||||
|     { | ||||
|         final String usera = createTestUser(); | ||||
|         final String userb = createTestUser(); | ||||
|         final String owner = createTestUser(); | ||||
|  | ||||
|         extendedReaders.add(usera); | ||||
|         extendedReaders.add(userb); | ||||
|         extendedWriters.add(usera); | ||||
|         extendedWriters.add(userb); | ||||
|  | ||||
|         AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); | ||||
|  | ||||
|         // Create a site | ||||
|         NodeRef documentLib = createSite(new HashSet<>(), new HashSet<>()); | ||||
|  | ||||
|         // Create records in the site document library | ||||
|         return createRecords(concurrentThreads, documentLib, owner); | ||||
|     } | ||||
|  | ||||
|     private NodeRef createSite(Set<String> readers, Set<String> writers) | ||||
|     { | ||||
|         return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>() { | ||||
|             @Override | ||||
|             public NodeRef execute() throws Throwable | ||||
|             { | ||||
|                 final String siteShortName = GUID.generate(); | ||||
|                 siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE); | ||||
|                 readers.forEach(reader -> siteService.setMembership(siteShortName, reader, SiteModel.SITE_CONSUMER)); | ||||
|                 writers.forEach(writer -> siteService.setMembership(siteShortName, writer, SiteModel.SITE_COLLABORATOR)); | ||||
|                 return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null); | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private Set<NodeRef> createRecords(int numRecords, NodeRef parent, String owner) | ||||
|     { | ||||
|         return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Set<NodeRef>>() { | ||||
|             @Override | ||||
|             public Set<NodeRef> execute() throws Throwable | ||||
|             { | ||||
|                 int createdRecords = 0; | ||||
|                 Set<NodeRef> documents = new HashSet<>(); | ||||
|                 while (createdRecords < numRecords) | ||||
|                 { | ||||
|                     final NodeRef doc = fileFolderService.create(parent, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef(); | ||||
|                     ownableService.setOwner(doc, owner); | ||||
|                     recordService.createRecord(filePlan, doc, rmFolder, true); | ||||
|                     recordService.file(doc); | ||||
|                     recordService.complete(doc); | ||||
|                     documents.add(doc); | ||||
|                     createdRecords++; | ||||
|                 } | ||||
|                 return documents; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers, boolean useRetry) | ||||
|     { | ||||
|         if (!useRetry) | ||||
|         { | ||||
|             setExtendedSecurity(doc, readers, writers); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() { | ||||
|             @Override | ||||
|             public Void execute() throws Throwable | ||||
|             { | ||||
|                 setExtendedSecurity(doc, readers, writers); | ||||
|                 return null; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers) | ||||
|     { | ||||
|         AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); | ||||
|         extendedSecurityService.set(doc, readers, writers); | ||||
|     } | ||||
|  | ||||
|     private void fireParallelExecutionOfSetExtendedSecurity(Set<NodeRef> documents, Set<String> extendedReaders, Set<String> extendedWriters, boolean useRetry) | ||||
|     { | ||||
|         CompletableFuture<?>[] futures = documents.stream() | ||||
|                 .map(doc -> CompletableFuture.runAsync(() -> setExtendedSecurity(doc, extendedReaders, extendedWriters, useRetry))) | ||||
|                 .toArray(CompletableFuture[]::new); | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             CompletableFuture.allOf(futures).join(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             Throwable cause = e.getCause(); | ||||
|             if (cause instanceof ConcurrencyFailureException) | ||||
|             { | ||||
|                 throw (ConcurrencyFailureException) cause; | ||||
|             } | ||||
|             throw new RuntimeException("Error during parallel execution", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void verifyCreatedGroups(Set<NodeRef> documents, boolean onlyDuplicatesValidation) | ||||
|     { | ||||
|         retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() { | ||||
|             @Override | ||||
|             public Void execute() throws Throwable | ||||
|             { | ||||
|                 Set<String> expectedAuthorities = null; | ||||
|                 Set<Set<String>> errors = new HashSet<>(); | ||||
|                 for (NodeRef doc : documents) | ||||
|                 { | ||||
|                     Set<AccessPermission> permissions = permissionService.getAllSetPermissions(doc); | ||||
|                     Set<String> authorities = getDocumentAuthorities(permissions); | ||||
|                     Set<String> authoritiesById = getAuthorityIds(authorities); | ||||
|  | ||||
|                     verifyIPRGroups(authorities, onlyDuplicatesValidation); | ||||
|  | ||||
|                     if (onlyDuplicatesValidation) | ||||
|                     { | ||||
|                         // Some documents may not have IPR groups created if there was a ConcurrencyFailureException | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     // All documents should have the same exact set of groups assigned | ||||
|                     if (expectedAuthorities == null) | ||||
|                     { | ||||
|                         expectedAuthorities = authoritiesById; | ||||
|                     } | ||||
|  | ||||
|                     if (!expectedAuthorities.equals(authoritiesById)) | ||||
|                     { | ||||
|                         errors.add(authoritiesById); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 assertTrue("Unexpected authorities linked to document", errors.isEmpty()); | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private Set<String> getDocumentAuthorities(Set<AccessPermission> permissions) | ||||
|     { | ||||
|         Set<String> authorities = new HashSet<>(); | ||||
|  | ||||
|         for (AccessPermission accessPermission : permissions) | ||||
|         { | ||||
|             String authority = accessPermission.getAuthority(); | ||||
|             String authName = authorityService.getName(AuthorityType.GROUP, authority); | ||||
|             authorities.add(authName); | ||||
|  | ||||
|         } | ||||
|         return authorities; | ||||
|     } | ||||
|  | ||||
|     private Set<String> getAuthorityIds(Set<String> authorities) | ||||
|     { | ||||
|         Set<String> authorityIds = new HashSet<>(); | ||||
|         for (String authority : authorities) | ||||
|         { | ||||
|             String authId = authorityService.getAuthorityNodeRef(authority) != null | ||||
|                     ? authorityService.getAuthorityNodeRef(authority).getId() | ||||
|                     : null; | ||||
|             authorityIds.add(authId); | ||||
|         } | ||||
|         return authorityIds; | ||||
|     } | ||||
|  | ||||
|     private void verifyIPRGroups(Set<String> authorities, boolean onlyDuplicatesValidation) | ||||
|     { | ||||
|         boolean hasGroupIPR = false; | ||||
|  | ||||
|         for (String authorityName : authorities) | ||||
|         { | ||||
|             String shortName = authorityService.getShortName(authorityName); | ||||
|  | ||||
|             if (authorityName.startsWith("GROUP_IPR")) | ||||
|             { | ||||
|                 hasGroupIPR = true; | ||||
|                 PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP, null, shortName, false, | ||||
|                         false, new PagingRequest(0, 10)); | ||||
|  | ||||
|                 assertEquals("No duplicated IPR group expected", 1, results.getPage().size()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!onlyDuplicatesValidation) | ||||
|         { | ||||
|             assertTrue("No IPR Groups created", hasGroupIPR); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -134,25 +134,6 @@ function doclist_main() | ||||
|       logger.log("doclist.lib.js - NodeRef: " + parsedArgs.nodeRef + " Query: " + query); | ||||
|  | ||||
|    favourites = sanitizeJunkFavouriteKeys(favourites); | ||||
|    if(query === null) | ||||
|    { | ||||
|       return { | ||||
|          luceneQuery: "", | ||||
|          paging: { | ||||
|             totalRecords: 0, | ||||
|             startIndex: 0 | ||||
|          }, | ||||
|          container: parsedArgs.rootNode, | ||||
|          parent: null, | ||||
|          onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"), | ||||
|          itemCount: { | ||||
|             folders: 0, | ||||
|             documents: 0 | ||||
|          }, | ||||
|          items: [], | ||||
|          customJSON: slingshotDocLib.getJSON() | ||||
|       }; | ||||
|    } | ||||
|  | ||||
|    if(Object.keys(favourites).length === 0 && query === null) | ||||
|    { | ||||
|   | ||||
| @@ -240,7 +240,7 @@ var Filters = | ||||
|                filterData = filterData.slice(0, -1); | ||||
|             } | ||||
|             filterQuery = this.constructPathQuery(parsedArgs); | ||||
|               filterParams.query = filterQuery + " +TAG:\"" + search.ISO9075Encode(filterData) + "\""; | ||||
|             filterParams.query = filterQuery + " +PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(filterData) + "/member\""; | ||||
|             break; | ||||
|  | ||||
|          case "category": | ||||
| @@ -249,15 +249,8 @@ var Filters = | ||||
|             { | ||||
|                filterData = filterData.slice(0, -1); | ||||
|             } | ||||
|  | ||||
|             var categoryNodeRef = this.getCategoryNodeRef(filterData); | ||||
|  | ||||
|             if (categoryNodeRef && search.findNode(categoryNodeRef) != null) { | ||||
|                filterParams.query = filterQuery + ' +@cm\\:categories:"' + categoryNodeRef + '"'; | ||||
|             } else { | ||||
|                logger.warn("category filter: skipping invalid category node : " + categoryNodeRef); | ||||
|             } | ||||
|             filterParams.language = "fts-alfresco"; | ||||
|             filterQuery = this.constructPathQuery(parsedArgs); | ||||
|             filterParams.query = filterQuery + " +PATH:\"/cm:categoryRoot/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\""; | ||||
|             break; | ||||
|  | ||||
|          case "aspect": | ||||
| @@ -278,24 +271,11 @@ var Filters = | ||||
|       { | ||||
|          filterParams.query += " " + (Filters.TYPE_MAP[parsedArgs.type] || ""); | ||||
|       } | ||||
|       logger.warn("Final Query : " + filterParams.query); | ||||
|  | ||||
|       return filterParams; | ||||
|    }, | ||||
|     | ||||
|     getCategoryNodeRef: function(categoryName) { | ||||
|         var results = search.luceneSearch( | ||||
|             'PATH:"/cm:categoryRoot/cm:generalclassifiable//*" AND @cm\\:name:"' + categoryName + '"' | ||||
|         ); | ||||
|  | ||||
|         if (results && results.length > 0) { | ||||
|             return results[0].nodeRef.toString(); | ||||
|         } | ||||
|  | ||||
|         logger.warn("Category not found: " + categoryName); | ||||
|         return null; | ||||
|     }, | ||||
|  | ||||
|    constructPathQuery: function(parsedArgs) | ||||
|    constructPathQuery: function constructPathQuery(parsedArgs) | ||||
|    { | ||||
|       var pathQuery = ""; | ||||
|       if (parsedArgs.libraryRoot != companyhome || parsedArgs.nodeRef != "alfresco://company/home") | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo</artifactId> | ||||
|       <version>25.3.0.46</version> | ||||
|       <version>25.3.0.33-SNAPSHOT</version> | ||||
|    </parent> | ||||
|  | ||||
|    <dependencies> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
|   | ||||
| @@ -9,6 +9,6 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
| </project> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| # More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat | ||||
| FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:00d89fb84bda7bb37c17b0117adb2cfe4f7cbddcd6c1e42b0a67ea8dbb41a734 | ||||
| FROM alfresco/alfresco-base-tomcat:tomcat10-jre21-rockylinux9@sha256:ed568167f4c28efc9db4c5bc44a882ee117c475463b526b21ada99e1b6d568dd | ||||
| # Set default docker_context. | ||||
| ARG resource_path=target | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <organization> | ||||
| @@ -16,11 +16,11 @@ | ||||
|     </organization> | ||||
|  | ||||
|     <properties> | ||||
|         <maven.build.sourceVersion>17</maven.build.sourceVersion> | ||||
|         <maven.build.sourceVersion>21</maven.build.sourceVersion> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> | ||||
|         <maven-release.version>2.5.3</maven-release.version> | ||||
|         <java.version>17</java.version> | ||||
|         <java.version>21</java.version> | ||||
|         <suiteXmlFile>${project.basedir}/src/test/resources/cmis-suite.xml</suiteXmlFile> | ||||
|         <cmis.binding /> | ||||
|         <cmis.basePath /> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
|   | ||||
| @@ -8,18 +8,18 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|         <suiteXmlFile>${project.basedir}/src/test/resources/restapi-suite.xml</suiteXmlFile> | ||||
|         <maven.build.sourceVersion>17</maven.build.sourceVersion> | ||||
|         <maven.build.sourceVersion>21</maven.build.sourceVersion> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <rest.api.explorer.branch>master</rest.api.explorer.branch> | ||||
|         <httpclient-osgi-version>4.5.6</httpclient-osgi-version> | ||||
|         <commons-lang3.version>3.18.0</commons-lang3.version> | ||||
|         <scribejava-apis.version>8.3.3</scribejava-apis.version> | ||||
|         <java.version>17</java.version> | ||||
|         <java.version>21</java.version> | ||||
|     </properties> | ||||
|  | ||||
|     <profiles> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
							
								
								
									
										30
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								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.3.0.46</version> | ||||
|     <version>25.3.0.33-SNAPSHOT</version> | ||||
|     <packaging>pom</packaging> | ||||
|     <name>Alfresco Community Repo Parent</name> | ||||
|  | ||||
| @@ -38,7 +38,7 @@ | ||||
|         <builder.name>entitled-builder</builder.name> | ||||
|         <local.registry>127.0.0.1:5000</local.registry> | ||||
|  | ||||
|         <java.version>17</java.version> | ||||
|         <java.version>21</java.version> | ||||
|         <maven.compiler.source>${java.version}</maven.compiler.source> | ||||
|         <maven.compiler.target>${java.version}</maven.compiler.target> | ||||
|         <maven.build.sourceVersion>${java.version}</maven.build.sourceVersion> | ||||
| @@ -51,13 +51,13 @@ | ||||
|         <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.2.2-A.4</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.2.2-A.2</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-transform-core.version>5.2.1</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.2.1</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version> | ||||
|         <dependency.acs-event-model.version>1.0.11</dependency.acs-event-model.version> | ||||
|         <dependency.acs-event-model.version>1.0.5</dependency.acs-event-model.version> | ||||
|  | ||||
|         <dependency.aspectj.version>1.9.22.1</dependency.aspectj.version> | ||||
|         <dependency.spring.version>6.2.11</dependency.spring.version> | ||||
|         <dependency.spring.version>6.2.8</dependency.spring.version> | ||||
|         <dependency.spring-security.version>6.3.9</dependency.spring-security.version> | ||||
|         <dependency.antlr.version>3.5.3</dependency.antlr.version> | ||||
|         <dependency.jackson.version>2.17.2</dependency.jackson.version> | ||||
| @@ -82,7 +82,7 @@ | ||||
|         <dependency.slf4j.version>2.0.16</dependency.slf4j.version> | ||||
|         <dependency.log4j.version>2.25.1</dependency.log4j.version> | ||||
|         <dependency.groovy.version>3.0.25</dependency.groovy.version> | ||||
|         <dependency.tika.version>3.2.3</dependency.tika.version> | ||||
|         <dependency.tika.version>2.9.2</dependency.tika.version> | ||||
|         <dependency.truezip.version>7.7.10</dependency.truezip.version> | ||||
|         <dependency.poi.version>5.4.0</dependency.poi.version> | ||||
|         <dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version> | ||||
| @@ -154,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.3.0.46</tag> | ||||
|         <tag>HEAD</tag> | ||||
|     </scm> | ||||
|  | ||||
|     <distributionManagement> | ||||
| @@ -170,12 +170,6 @@ | ||||
|  | ||||
|     <dependencyManagement> | ||||
|         <dependencies> | ||||
|             <!-- v1.10 has 0BSD license it must be consulted with Legal --> | ||||
|             <dependency> | ||||
|                 <groupId>org.tukaani</groupId> | ||||
|                 <artifactId>xz</artifactId> | ||||
|                 <version>1.9</version> | ||||
|             </dependency> | ||||
|             <!-- Jakarta... --> | ||||
|             <dependency> | ||||
|                 <groupId>jakarta.xml.bind</groupId> | ||||
| @@ -1131,10 +1125,16 @@ | ||||
|                                             <exclude>jakarta.xml.soap:jakarta.xml.soap-api:(, 2.0.1)</exclude> | ||||
|                                             <exclude>jakarta.jws:jakarta.jws-api:(, 3.0.0)</exclude> | ||||
| <!--                                            Enforce ban bouncycastle dependencies other than specified under <includes> section--> | ||||
|                                             <exclude>org.bouncycastle:(,1.81)</exclude> | ||||
|                                             <exclude>org.bouncycastle</exclude> | ||||
| <!--                                            Enforce one version of Jaxb--> | ||||
|                                             <exclude>com.sun.xml.bind</exclude> | ||||
|                                         </excludes> | ||||
|                                         <includes> | ||||
|                                             <include>org.bouncycastle:bcprov-jdk18on:[1.78.1,)</include> | ||||
|                                             <include>org.bouncycastle:bcmail-jdk18on:[1.78.1,)</include> | ||||
|                                             <include>org.bouncycastle:bcpkix-jdk18on:[1.78.1,)</include> | ||||
|                                             <include>org.bouncycastle:bcutil-jdk18on:[1.78.1,)</include> | ||||
|                                         </includes> | ||||
|                                     </bannedDependencies> | ||||
|                                 </rules> | ||||
|                                 <fail>true</fail> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.3.0.46</version> | ||||
|         <version>25.3.0.33-SNAPSHOT</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -840,12 +840,12 @@ | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|                 <configuration> | ||||
|                     <complianceLevel>17</complianceLevel> | ||||
|                     <complianceLevel>${java.version}</complianceLevel> | ||||
|                     <outxml>false</outxml> | ||||
|                     <verbose>true</verbose> | ||||
|                     <showWeaveInfo>true</showWeaveInfo> | ||||
|                     <source>17</source> | ||||
|                     <target>17</target> | ||||
|                     <source>${java.version}</source> | ||||
|                     <target>${java.version}</target> | ||||
|                     <additionalCompilerArgs> | ||||
|                         <arg>-parameters</arg> | ||||
|                     </additionalCompilerArgs> | ||||
|   | ||||
| @@ -70,13 +70,6 @@ public interface AuditComponent | ||||
|      */ | ||||
|     public void setUserAuditFilter(UserAuditFilter userAuditFilter); | ||||
|  | ||||
|     /** | ||||
|      * @param auditRecordReporter | ||||
|      *            AuditRecordReporter | ||||
|      * @since 25.3 | ||||
|      */ | ||||
|     public void setAuditRecordReporter(AuditRecordReporter auditRecordReporter); | ||||
|  | ||||
|     /** | ||||
|      * Get all registered audit applications, whether active or not. | ||||
|      * | ||||
|   | ||||
| @@ -48,6 +48,7 @@ import org.alfresco.repo.audit.model.AuditModelRegistryImpl; | ||||
| import org.alfresco.repo.domain.audit.AuditDAO; | ||||
| import org.alfresco.repo.domain.propval.PropertyValueDAO; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationUtil; | ||||
| import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; | ||||
| import org.alfresco.repo.transaction.AlfrescoTransactionSupport; | ||||
| import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; | ||||
| import org.alfresco.repo.transaction.RetryingTransactionHelper; | ||||
| @@ -72,8 +73,8 @@ public class AuditComponentImpl implements AuditComponent | ||||
| { | ||||
|     private static final String INBOUND_LOGGER = "org.alfresco.repo.audit.inbound"; | ||||
|  | ||||
|     private static final Log logger = LogFactory.getLog(AuditComponentImpl.class); | ||||
|     private static final Log loggerInbound = LogFactory.getLog(INBOUND_LOGGER); | ||||
|     private static Log logger = LogFactory.getLog(AuditComponentImpl.class); | ||||
|     private static Log loggerInbound = LogFactory.getLog(INBOUND_LOGGER); | ||||
|  | ||||
|     private AuditModelRegistryImpl auditModelRegistry; | ||||
|     private PropertyValueDAO propertyValueDAO; | ||||
| @@ -81,7 +82,6 @@ public class AuditComponentImpl implements AuditComponent | ||||
|     private TransactionService transactionService; | ||||
|     private AuditFilter auditFilter; | ||||
|     private UserAuditFilter userAuditFilter; | ||||
|     private AuditRecordReporter auditRecordReporter; | ||||
|  | ||||
|     /** | ||||
|      * Default constructor | ||||
| @@ -140,11 +140,6 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         this.userAuditFilter = userAuditFilter; | ||||
|     } | ||||
|  | ||||
|     public void setAuditRecordReporter(AuditRecordReporter auditRecordReporter) | ||||
|     { | ||||
|         this.auditRecordReporter = auditRecordReporter; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      * | ||||
| @@ -220,7 +215,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|     public int deleteAuditEntries(List<Long> auditEntryIds) | ||||
|     { | ||||
|         // Shortcut, if necessary | ||||
|         if (auditEntryIds.isEmpty()) | ||||
|         if (auditEntryIds.size() == 0) | ||||
|         { | ||||
|             return 0; | ||||
|         } | ||||
| @@ -239,7 +234,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         { | ||||
|             Long disabledPathsId = application.getDisabledPathsId(); | ||||
|             Set<String> disabledPaths = (Set<String>) propertyValueDAO.getPropertyById(disabledPathsId); | ||||
|             return new HashSet<>(disabledPaths); | ||||
|             return new HashSet<String>(disabledPaths); | ||||
|         } | ||||
|         catch (Throwable e) | ||||
|         { | ||||
| @@ -259,16 +254,6 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         return auditModelRegistry.isAuditEnabled(); | ||||
|     } | ||||
|  | ||||
|     public boolean isAuditingToDatabaseEnabled() | ||||
|     { | ||||
|         return auditModelRegistry.isAuditingToDatabaseEnabled(); | ||||
|     } | ||||
|  | ||||
|     public boolean isAuditingToAuditStorageEnabled() | ||||
|     { | ||||
|         return auditModelRegistry.isAuditingToAuditStorageEnabled(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      * | ||||
| @@ -324,7 +309,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|     { | ||||
|         PathMapper pathMapper = auditModelRegistry.getAuditPathMapper(); | ||||
|         Set<String> mappedPaths = pathMapper.getMappedPathsWithPartialMatch(path); | ||||
|         return loggerInbound.isDebugEnabled() || !mappedPaths.isEmpty(); | ||||
|         return loggerInbound.isDebugEnabled() || mappedPaths.size() > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -361,7 +346,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|  | ||||
|         // Check if there are any entries that match or supercede the given path | ||||
|         String disablingPath = null; | ||||
|  | ||||
|         ; | ||||
|         for (String disabledPath : disabledPaths) | ||||
|         { | ||||
|             if (path.startsWith(disabledPath)) | ||||
| @@ -588,7 +573,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         } | ||||
|  | ||||
|         // Build the key paths using the session root path | ||||
|         Map<String, Serializable> pathedValues = new HashMap<>(values.size() * 2); | ||||
|         Map<String, Serializable> pathedValues = new HashMap<String, Serializable>(values.size() * 2); | ||||
|         for (Map.Entry<String, Serializable> entry : values.entrySet()) | ||||
|         { | ||||
|             String pathElement = entry.getKey(); | ||||
| @@ -611,7 +596,12 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         case TXN_NONE: | ||||
|         case TXN_READ_ONLY: | ||||
|             // New transaction | ||||
|             RetryingTransactionCallback<Map<String, Serializable>> callback = () -> recordAuditValuesImpl(mappedValues); | ||||
|             RetryingTransactionCallback<Map<String, Serializable>> callback = new RetryingTransactionCallback<Map<String, Serializable>>() { | ||||
|                 public Map<String, Serializable> execute() throws Throwable | ||||
|                 { | ||||
|                     return recordAuditValuesImpl(mappedValues); | ||||
|                 } | ||||
|             }; | ||||
|             RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper(); | ||||
|             txnHelper.setForceWritable(true); | ||||
|             return txnHelper.doInTransaction(callback, false, true); | ||||
| @@ -628,16 +618,21 @@ public class AuditComponentImpl implements AuditComponent | ||||
|     public Map<String, Serializable> recordAuditValuesImpl(Map<String, Serializable> mappedValues) | ||||
|     { | ||||
|         // Group the values by root path | ||||
|         Map<String, Map<String, Serializable>> mappedValuesByRootKey = new HashMap<>(); | ||||
|         Map<String, Map<String, Serializable>> mappedValuesByRootKey = new HashMap<String, Map<String, Serializable>>(); | ||||
|         for (Map.Entry<String, Serializable> entry : mappedValues.entrySet()) | ||||
|         { | ||||
|             String path = entry.getKey(); | ||||
|             String rootKey = AuditApplication.getRootKey(path); | ||||
|             Map<String, Serializable> rootKeyMappedValues = mappedValuesByRootKey.computeIfAbsent(rootKey, k -> new HashMap<>(7)); | ||||
|             Map<String, Serializable> rootKeyMappedValues = mappedValuesByRootKey.get(rootKey); | ||||
|             if (rootKeyMappedValues == null) | ||||
|             { | ||||
|                 rootKeyMappedValues = new HashMap<String, Serializable>(7); | ||||
|                 mappedValuesByRootKey.put(rootKey, rootKeyMappedValues); | ||||
|             } | ||||
|             rootKeyMappedValues.put(path, entry.getValue()); | ||||
|         } | ||||
|  | ||||
|         Map<String, Serializable> allAuditedValues = new HashMap<>(mappedValues.size() * 2 + 1); | ||||
|         Map<String, Serializable> allAuditedValues = new HashMap<String, Serializable>(mappedValues.size() * 2 + 1); | ||||
|         // Now audit for each of the root keys | ||||
|         for (Map.Entry<String, Map<String, Serializable>> entry : mappedValuesByRootKey.entrySet()) | ||||
|         { | ||||
| @@ -699,7 +694,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         } | ||||
|  | ||||
|         // Check if there is anything to audit | ||||
|         if (values.isEmpty()) | ||||
|         if (values.size() == 0) | ||||
|         { | ||||
|             if (logger.isDebugEnabled()) | ||||
|             { | ||||
| @@ -732,7 +727,12 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         Map<String, Serializable> auditData = generateData(generators); | ||||
|  | ||||
|         // Now extract values | ||||
|         Map<String, Serializable> extractedData = AuthenticationUtil.runAs(() -> extractData(application, values), AuthenticationUtil.getSystemUserName()); | ||||
|         Map<String, Serializable> extractedData = AuthenticationUtil.runAs(new RunAsWork<Map<String, Serializable>>() { | ||||
|             public Map<String, Serializable> doWork() throws Exception | ||||
|             { | ||||
|                 return extractData(application, values); | ||||
|             } | ||||
|         }, AuthenticationUtil.getSystemUserName()); | ||||
|  | ||||
|         // Combine extracted and generated values (extracted data takes precedence) | ||||
|         auditData.putAll(extractedData); | ||||
| @@ -743,8 +743,8 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         { | ||||
|             String root = value.getKey(); | ||||
|             int index = root.lastIndexOf("/"); | ||||
|             Map<String, Serializable> argc = new HashMap<>(1); | ||||
|             argc.put(root.substring(index).substring(1), value.getValue()); | ||||
|             Map<String, Serializable> argc = new HashMap<String, Serializable>(1); | ||||
|             argc.put(root.substring(index, root.length()).substring(1), value.getValue()); | ||||
|             if (!auditFilter.accept(root.substring(0, index), argc)) | ||||
|             { | ||||
|                 return Collections.emptyMap(); | ||||
| @@ -760,15 +760,10 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         { | ||||
|             // Persist the values (if not just gathering data in a pre call for use in a post call) | ||||
|             boolean justGatherPreCallData = application.isApplicationJustGeneratingPreCallData(); | ||||
|             if (!justGatherPreCallData && isAuditingToDatabaseEnabled()) | ||||
|             if (!justGatherPreCallData) | ||||
|             { | ||||
|                 entryId = auditDAO.createAuditEntry(applicationId, time, username, auditData); | ||||
|             } | ||||
|             if (isAuditingToAuditStorageEnabled()) | ||||
|             { | ||||
|                 auditRecordReporter.reportAuditRecord(createAuditRecord(auditData, true, username, entryId, application.getApplicationName())); | ||||
|             } | ||||
|  | ||||
|             // Done | ||||
|             if (logger.isDebugEnabled()) | ||||
|             { | ||||
| @@ -827,7 +822,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|             AuditApplication application, | ||||
|             Map<String, Serializable> values) | ||||
|     { | ||||
|         Map<String, Serializable> newData = new HashMap<>(values.size()); | ||||
|         Map<String, Serializable> newData = new HashMap<String, Serializable>(values.size()); | ||||
|  | ||||
|         List<DataExtractorDefinition> extractors = application.getDataExtractors(); | ||||
|         for (DataExtractorDefinition extractorDef : extractors) | ||||
| @@ -905,7 +900,7 @@ public class AuditComponentImpl implements AuditComponent | ||||
|      */ | ||||
|     private Map<String, Serializable> generateData(Map<String, DataGenerator> generators) | ||||
|     { | ||||
|         Map<String, Serializable> newData = new HashMap<>(generators.size() + 5); | ||||
|         Map<String, Serializable> newData = new HashMap<String, Serializable>(generators.size() + 5); | ||||
|         for (Map.Entry<String, DataGenerator> entry : generators.entrySet()) | ||||
|         { | ||||
|             String path = entry.getKey(); | ||||
| @@ -930,20 +925,6 @@ public class AuditComponentImpl implements AuditComponent | ||||
|         return newData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates an AuditRecord from the provided audit data. | ||||
|      */ | ||||
|     private AuditRecord createAuditRecord(Map<String, Serializable> auditData, boolean inTransaction, String username, Long entryId, String applicationName) | ||||
|     { | ||||
|         int rootSize = applicationName.length() + 2; // Root is constructed like this -> '/' + auditedApplicationName + '/'. | ||||
|         AuditRecord.Builder builder = AuditRecordUtils.generateAuditRecordBuilder(auditData, rootSize); | ||||
|         builder.setAuditRecordType(applicationName); | ||||
|         builder.setInTransaction(inTransaction); | ||||
|         builder.setUsername(username); | ||||
|         builder.setEntryDBId(entryId); | ||||
|         return builder.build(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      */ | ||||
|   | ||||
| @@ -1,130 +0,0 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 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.repo.audit; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.ZonedDateTime; | ||||
| import java.util.Map; | ||||
|  | ||||
| public class AuditRecord | ||||
| { | ||||
|     private final boolean inTransaction; | ||||
|     private final String auditApplicationId; | ||||
|     private final ZonedDateTime createdAt; | ||||
|     private final String username; | ||||
|     private final Long entryDBId; | ||||
|     private final Map<String, Serializable> auditData; | ||||
|  | ||||
|     public AuditRecord(Builder builder) | ||||
|     { | ||||
|         this.auditApplicationId = builder.auditRecordType; | ||||
|         this.inTransaction = builder.inTransaction; | ||||
|         this.auditData = builder.auditRecordData; | ||||
|         this.createdAt = ZonedDateTime.now(); | ||||
|         this.username = builder.username; | ||||
|         this.entryDBId = builder.entryDBId; | ||||
|     } | ||||
|  | ||||
|     public String getAuditApplicationId() | ||||
|     { | ||||
|         return auditApplicationId; | ||||
|     } | ||||
|  | ||||
|     public boolean isInTransaction() | ||||
|     { | ||||
|         return inTransaction; | ||||
|     } | ||||
|  | ||||
|     public ZonedDateTime getCreatedAt() | ||||
|     { | ||||
|         return createdAt; | ||||
|     } | ||||
|  | ||||
|     public String getUsername() | ||||
|     { | ||||
|         return username; | ||||
|     } | ||||
|  | ||||
|     public Long getEntryDBId() | ||||
|     { | ||||
|         return entryDBId; | ||||
|     } | ||||
|  | ||||
|     public Map<String, Serializable> getAuditData() | ||||
|     { | ||||
|         return auditData; | ||||
|     } | ||||
|  | ||||
|     public static Builder builder() | ||||
|     { | ||||
|         return new Builder(); | ||||
|     } | ||||
|  | ||||
|     public static class Builder | ||||
|     { | ||||
|         private String auditRecordType; | ||||
|         private boolean inTransaction; | ||||
|         private Map<String, Serializable> auditRecordData; | ||||
|         private String username; | ||||
|         private Long entryDBId; | ||||
|  | ||||
|         public Builder setAuditRecordType(String auditRecordType) | ||||
|         { | ||||
|             this.auditRecordType = auditRecordType; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public Builder setInTransaction(boolean inTransaction) | ||||
|         { | ||||
|             this.inTransaction = inTransaction; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public Builder setAuditRecordData(Map<String, Serializable> auditRecordData) | ||||
|         { | ||||
|             this.auditRecordData = auditRecordData; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public Builder setUsername(String username) | ||||
|         { | ||||
|             this.username = username; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public Builder setEntryDBId(Long entryDBId) | ||||
|         { | ||||
|             this.entryDBId = entryDBId; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public AuditRecord build() | ||||
|         { | ||||
|             return new AuditRecord(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 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.repo.audit; | ||||
|  | ||||
| public interface AuditRecordReporter | ||||
| { | ||||
|     /** | ||||
|      * This method will report AuditRecord to Audit Storage using RepoEvent2 | ||||
|      *  | ||||
|      * @param auditRecord | ||||
|      *            represent data that will be reported. | ||||
|      */ | ||||
|     void reportAuditRecord(AuditRecord auditRecord); | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 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.repo.audit; | ||||
|  | ||||
| public class AuditRecordReporterImpl implements AuditRecordReporter | ||||
| { | ||||
|     /** | ||||
|      * This method intentionally has an empty implementation. | ||||
|      * <p> | ||||
|      * This class provides a no-op implementation of {@link AuditRecordReporter}. | ||||
|      */ | ||||
|     @Override | ||||
|     public void reportAuditRecord(AuditRecord auditRecord) | ||||
|     { | ||||
|         // No operation performed. | ||||
|     } | ||||
| } | ||||
| @@ -1,104 +0,0 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 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.repo.audit; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| public final class AuditRecordUtils | ||||
| { | ||||
|     private AuditRecordUtils() | ||||
|     { | ||||
|         // This is a utility class and cannot be instantiated. | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generates an {@link AuditRecord.Builder} from flat audit data. | ||||
|      * <p> | ||||
|      * This method: | ||||
|      * <ul> | ||||
|      * <li>Translates flat {@code key-value} pairs into a nested JSON structure.</li> | ||||
|      * <li>Preloads the builder with the provided arguments.</li> | ||||
|      * <li>Splits keys by {@code /} to build the nested structure.</li> | ||||
|      * <li>Uses the root key as the application ID.</li> | ||||
|      * <li>Assumes each key starts with the same root, constructed as {@code '/' + auditedApplicationName + '/'}, which is removed before splitting.</li> | ||||
|      * </ul> | ||||
|      * | ||||
|      * @param data | ||||
|      *            a map containing flat audit data as `key-value` pairs | ||||
|      * @param keyRootLength | ||||
|      *            is a length of key root. | ||||
|      * @return a preloaded {@link AuditRecord.Builder} | ||||
|      */ | ||||
|     public static AuditRecord.Builder generateAuditRecordBuilder(Map<String, Serializable> data, int keyRootLength) | ||||
|     { | ||||
|         var auditRecordBuilder = AuditRecord.builder(); | ||||
|  | ||||
|         var rootNode = createRootNode(data, keyRootLength); | ||||
|  | ||||
|         auditRecordBuilder.setAuditRecordData(rootNode); | ||||
|  | ||||
|         return auditRecordBuilder; | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("unchecked") | ||||
|     private static HashMap<String, Serializable> createRootNode(Map<String, Serializable> data, int keyRootLength) | ||||
|     { | ||||
|         var rootNode = new HashMap<String, Serializable>(); | ||||
|  | ||||
|         data.forEach((k, v) -> { | ||||
|             var keys = k.substring(keyRootLength).split("/"); | ||||
|  | ||||
|             var current = rootNode; | ||||
|             for (int i = 0; i < keys.length - 1; i++) | ||||
|             { | ||||
|                 current = (HashMap<String, Serializable>) current.computeIfAbsent(keys[i], newMap -> new HashMap<String, Serializable>()); | ||||
|             } | ||||
|             current.put(keys[keys.length - 1], decodeValueByInstance(v)); | ||||
|         }); | ||||
|         return rootNode; | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("unchecked") | ||||
|     private static Serializable decodeValueByInstance(Serializable value) | ||||
|     { | ||||
|         if (value instanceof HashMap<?, ?>) | ||||
|         { | ||||
|             return createRootNode((HashMap<String, Serializable>) value, 0); | ||||
|         } | ||||
|         else if (value instanceof NodeRef) | ||||
|         { | ||||
|             return ((NodeRef) value).getId(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -58,21 +58,6 @@ public interface AuditModelRegistry | ||||
|      */ | ||||
|     public boolean isAuditEnabled(); | ||||
|  | ||||
|     /** | ||||
|      * Determines whether audit values should be stored in database. <code>True</code> by default if not changed by property. | ||||
|      * | ||||
|      * @return <code>true</code> if audit is enabled. | ||||
|      */ | ||||
|     boolean isAuditingToDatabaseEnabled(); | ||||
|  | ||||
|     /** | ||||
|      * Determines whether audit values should be stored in audit storage. | ||||
|      *  | ||||
|      * @return <code>true</code> if auditing to Audit Storage is enabled. | ||||
|      * | ||||
|      */ | ||||
|     boolean isAuditingToAuditStorageEnabled(); | ||||
|  | ||||
|     /** | ||||
|      * Get a map of all audit applications key by name | ||||
|      *  | ||||
|   | ||||
| @@ -85,9 +85,6 @@ public class AuditModelRegistryImpl extends AbstractPropertyBackedBean implement | ||||
| { | ||||
|     /** The name of the global enablement property. */ | ||||
|     public static final String PROPERTY_AUDIT_ENABLED = "audit.enabled"; | ||||
|  | ||||
|     private static final String AUDITING_TO_DATABASE = ".auditingToDatabase"; | ||||
|     private static final String AUDITING_TO_AUDIT_STORAGE = ".auditingToAuditStorage"; | ||||
|     /** The name of the strict loading flag. */ | ||||
|     public static final String PROPERTY_AUDIT_CONFIG_STRICT = "audit.config.strict"; | ||||
|     /** The XSD classpath location. */ | ||||
| @@ -252,26 +249,6 @@ public class AuditModelRegistryImpl extends AbstractPropertyBackedBean implement | ||||
|         return value != null && value.equalsIgnoreCase("true"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean isAuditingToDatabaseEnabled() | ||||
|     { | ||||
|         String value = getProperty(AUDIT_PROPERTY_AUDIT_ENABLED + AUDITING_TO_DATABASE); | ||||
|         return value == null || value.equalsIgnoreCase("true"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean isAuditingToAuditStorageEnabled() | ||||
|     { | ||||
|         String value = getProperty(AUDIT_PROPERTY_AUDIT_ENABLED + AUDITING_TO_AUDIT_STORAGE); | ||||
|         return value != null && value.equalsIgnoreCase("true"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Enables audit and registers an audit model at a given URL. Does not register across the cluster and should only be used for unit test purposes. | ||||
|      *  | ||||
| @@ -319,8 +296,6 @@ public class AuditModelRegistryImpl extends AbstractPropertyBackedBean implement | ||||
|  | ||||
|             // Default value for global enabled property | ||||
|             properties.put(AUDIT_PROPERTY_AUDIT_ENABLED, false); | ||||
|             properties.put(AUDIT_PROPERTY_AUDIT_ENABLED + AUDITING_TO_DATABASE, true); | ||||
|             properties.put(AUDIT_PROPERTY_AUDIT_ENABLED + AUDITING_TO_AUDIT_STORAGE, false); | ||||
|  | ||||
|             // Let's search for config files in the appropriate places. The individual applications they contain can still | ||||
|             // be enabled/disabled by the bean properties | ||||
|   | ||||
| @@ -2066,7 +2066,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO | ||||
|  | ||||
|         Node node = getNodeNotNull(nodeId, false); | ||||
|         // Handle sys:referenceable | ||||
|         ReferenceablePropertiesEntity.addReferenceableProperties(node.getId(), node.getNodeRef(), props); | ||||
|         ReferenceablePropertiesEntity.addReferenceableProperties(node, props); | ||||
|         // Handle sys:localized | ||||
|         LocalizedPropertiesEntity.addLocalizedProperties(localeDAO, node, props); | ||||
|         // Handle cm:auditable | ||||
|   | ||||
| @@ -86,8 +86,10 @@ public class ReferenceablePropertiesEntity | ||||
|     /** | ||||
|      * Adds all {@link ContentModel#ASPECT_REFERENCEABLE referencable} properties. | ||||
|      */ | ||||
|     public static void addReferenceableProperties(Long nodeId, NodeRef nodeRef, Map<QName, Serializable> properties) | ||||
|     public static void addReferenceableProperties(Node node, Map<QName, Serializable> properties) | ||||
|     { | ||||
|         Long nodeId = node.getId(); | ||||
|         NodeRef nodeRef = node.getNodeRef(); | ||||
|         properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol()); | ||||
|         properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); | ||||
|         properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId()); | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2020 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,7 +38,7 @@ import org.alfresco.util.Pair; | ||||
|  */ | ||||
| public enum EventJSONSchema | ||||
| { | ||||
|     NODE_CREATED_V1("nodeCreated", 1, EventType.NODE_CREATED), NODE_UPDATED_V1("nodeUpdated", 1, EventType.NODE_UPDATED), NODE_DELETED_V1("nodeDeleted", 1, EventType.NODE_DELETED), CHILD_ASSOC_CREATED_V1("childAssocCreated", 1, EventType.CHILD_ASSOC_CREATED), CHILD_ASSOC_DELETED_V1("childAssocDeleted", 1, EventType.CHILD_ASSOC_DELETED), PEER_ASSOC_CREATED_V1("peerAssocCreated", 1, EventType.PEER_ASSOC_CREATED), PEER_ASSOC_DELETED_V1("peerAssocDeleted", 1, EventType.PEER_ASSOC_DELETED), PERMISSION_UPDATED_V1("permissionUpdated", 1, EventType.PERMISSION_UPDATED), AUDIT_ENTRY_CREATED_V1("auditEntryCreated", 1, EventType.AUDIT_ENTRY_CREATED); | ||||
|     NODE_CREATED_V1("nodeCreated", 1, EventType.NODE_CREATED), NODE_UPDATED_V1("nodeUpdated", 1, EventType.NODE_UPDATED), NODE_DELETED_V1("nodeDeleted", 1, EventType.NODE_DELETED), CHILD_ASSOC_CREATED_V1("childAssocCreated", 1, EventType.CHILD_ASSOC_CREATED), CHILD_ASSOC_DELETED_V1("childAssocDeleted", 1, EventType.CHILD_ASSOC_DELETED), PEER_ASSOC_CREATED_V1("peerAssocCreated", 1, EventType.PEER_ASSOC_CREATED), PEER_ASSOC_DELETED_V1("peerAssocDeleted", 1, EventType.PEER_ASSOC_DELETED), PERMISSION_UPDATED_V1("permissionUpdated", 1, EventType.PERMISSION_UPDATED); | ||||
|  | ||||
|     private static final String PREFIX = "https://api.alfresco.com/schema/event/repo/v"; | ||||
|  | ||||
|   | ||||
| @@ -28,10 +28,8 @@ package org.alfresco.repo.node.getchildren; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.alfresco.repo.domain.node.AuditablePropertiesEntity; | ||||
| import org.alfresco.repo.domain.node.NodeEntity; | ||||
| import org.alfresco.repo.domain.node.NodePropertyEntity; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.StoreRef; | ||||
|  | ||||
| /** | ||||
|  * Filterable/Sortable Node Entity | ||||
| @@ -44,17 +42,12 @@ import org.alfresco.service.cmr.repository.StoreRef; | ||||
| public class FilterSortNodeEntity | ||||
| { | ||||
|     private Long id; // node id | ||||
|     private String nodeUuid; | ||||
|     private Long typeQNameId; | ||||
|  | ||||
|     private AuditablePropertiesEntity auditablePropertiesEntity; | ||||
|     private NodeEntity node; | ||||
|     private NodePropertyEntity prop1; | ||||
|     private NodePropertyEntity prop2; | ||||
|     private NodePropertyEntity prop3; | ||||
|  | ||||
|     private String storeProtocol; | ||||
|     private String storeIdentifier; | ||||
|  | ||||
|     // Supplemental query-related parameters | ||||
|     private Long parentNodeId; | ||||
|     private Long prop1qnameId; | ||||
| @@ -87,26 +80,6 @@ public class FilterSortNodeEntity | ||||
|         this.id = id; | ||||
|     } | ||||
|  | ||||
|     public String getNodeUuid() | ||||
|     { | ||||
|         return nodeUuid; | ||||
|     } | ||||
|  | ||||
|     public void setNodeUuid(String nodeUuid) | ||||
|     { | ||||
|         this.nodeUuid = nodeUuid; | ||||
|     } | ||||
|  | ||||
|     public Long getTypeQNameId() | ||||
|     { | ||||
|         return typeQNameId; | ||||
|     } | ||||
|  | ||||
|     public void setTypeQNameId(Long typeQNameId) | ||||
|     { | ||||
|         this.typeQNameId = typeQNameId; | ||||
|     } | ||||
|  | ||||
|     public String getPattern() | ||||
|     { | ||||
|         return pattern; | ||||
| @@ -163,16 +136,6 @@ public class FilterSortNodeEntity | ||||
|         this.namePropertyQNameId = namePropertyQNameId; | ||||
|     } | ||||
|  | ||||
|     public AuditablePropertiesEntity getAuditablePropertiesEntity() | ||||
|     { | ||||
|         return auditablePropertiesEntity; | ||||
|     } | ||||
|  | ||||
|     public void setAuditablePropertiesEntity(AuditablePropertiesEntity auditablePropertiesEntity) | ||||
|     { | ||||
|         this.auditablePropertiesEntity = auditablePropertiesEntity; | ||||
|     } | ||||
|  | ||||
|     public NodePropertyEntity getProp1() | ||||
|     { | ||||
|         return prop1; | ||||
| @@ -203,24 +166,14 @@ public class FilterSortNodeEntity | ||||
|         this.prop3 = prop3; | ||||
|     } | ||||
|  | ||||
|     public String getStoreProtocol() | ||||
|     public NodeEntity getNode() | ||||
|     { | ||||
|         return storeProtocol; | ||||
|         return node; | ||||
|     } | ||||
|  | ||||
|     public void setStoreProtocol(String storeProtocol) | ||||
|     public void setNode(NodeEntity childNode) | ||||
|     { | ||||
|         this.storeProtocol = storeProtocol; | ||||
|     } | ||||
|  | ||||
|     public String getStoreIdentifier() | ||||
|     { | ||||
|         return storeIdentifier; | ||||
|     } | ||||
|  | ||||
|     public void setStoreIdentifier(String storeIdentifier) | ||||
|     { | ||||
|         this.storeIdentifier = storeIdentifier; | ||||
|         this.node = childNode; | ||||
|     } | ||||
|  | ||||
|     // Supplemental query-related parameters | ||||
| @@ -304,9 +257,4 @@ public class FilterSortNodeEntity | ||||
|     { | ||||
|         this.isPrimary = isPrimary; | ||||
|     } | ||||
|  | ||||
|     public NodeRef createNodeRef() | ||||
|     { | ||||
|         return new NodeRef(new StoreRef(storeProtocol, storeIdentifier), nodeUuid); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,7 @@ import org.alfresco.query.CannedQueryParameters; | ||||
| import org.alfresco.query.CannedQuerySortDetails; | ||||
| import org.alfresco.query.CannedQuerySortDetails.SortOrder; | ||||
| import org.alfresco.repo.domain.node.AuditablePropertiesEntity; | ||||
| import org.alfresco.repo.domain.node.Node; | ||||
| import org.alfresco.repo.domain.node.NodeDAO; | ||||
| import org.alfresco.repo.domain.node.NodeEntity; | ||||
| import org.alfresco.repo.domain.node.NodePropertyEntity; | ||||
| @@ -774,8 +775,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR | ||||
|             if (results.size() >= BATCH_SIZE) | ||||
|             { | ||||
|                 // batch | ||||
|                 preloadNodes(); | ||||
|                 filterSort(); | ||||
|                 preloadFilterSort(); | ||||
|             } | ||||
|  | ||||
|             results.add(result); | ||||
| @@ -788,27 +788,24 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR | ||||
|             if (results.size() >= 0) | ||||
|             { | ||||
|                 // finish batch | ||||
|                 preloadNodes(); | ||||
|                 filterSort(); | ||||
|                 preloadFilterSort(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void preloadNodes() | ||||
|         private void preloadFilterSort() | ||||
|         { | ||||
|             List<NodeRef> nodeRefs = new ArrayList<>(results.size()); | ||||
|             for (FilterSortNodeEntity result : results) | ||||
|             { | ||||
|                 nodeRefs.add(result.createNodeRef()); | ||||
|                 nodeRefs.add(result.getNode().getNodeRef()); | ||||
|             } | ||||
|  | ||||
|             preload(nodeRefs); | ||||
|         } | ||||
|  | ||||
|         private void filterSort() | ||||
|         { | ||||
|             for (FilterSortNodeEntity result : results) | ||||
|             { | ||||
|                 NodeRef nodeRef = result.createNodeRef(); | ||||
|                 Node node = result.getNode(); | ||||
|                 NodeRef nodeRef = node.getNodeRef(); | ||||
|  | ||||
|                 Map<NodePropertyKey, NodePropertyValue> propertyValues = new HashMap<NodePropertyKey, NodePropertyValue>(3); | ||||
|  | ||||
| @@ -833,7 +830,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR | ||||
|                 Map<QName, Serializable> propVals = nodePropertyHelper.convertToPublicProperties(propertyValues); | ||||
|  | ||||
|                 // Add referenceable / spoofed properties (including spoofed name if null) | ||||
|                 ReferenceablePropertiesEntity.addReferenceableProperties(result.getId(), nodeRef, propVals); | ||||
|                 ReferenceablePropertiesEntity.addReferenceableProperties(node, propVals); | ||||
|  | ||||
|                 // special cases | ||||
|  | ||||
| @@ -855,7 +852,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR | ||||
|                 } | ||||
|  | ||||
|                 // Auditable props (eg. cm:creator, cm:created, cm:modifier, cm:modified, ...) | ||||
|                 AuditablePropertiesEntity auditableProps = result.getAuditablePropertiesEntity(); | ||||
|                 AuditablePropertiesEntity auditableProps = node.getAuditableProperties(); | ||||
|                 if (auditableProps != null) | ||||
|                 { | ||||
|                     for (Map.Entry<QName, Serializable> entry : auditableProps.getAuditableProperties().entrySet()) | ||||
| @@ -865,7 +862,7 @@ public class GetChildrenCannedQuery extends AbstractCannedQueryPermissions<NodeR | ||||
|                 } | ||||
|  | ||||
|                 // Node type | ||||
|                 Long nodeTypeQNameId = result.getTypeQNameId(); | ||||
|                 Long nodeTypeQNameId = node.getTypeQNameId(); | ||||
|                 if (nodeTypeQNameId != null) | ||||
|                 { | ||||
|                     Pair<Long, QName> pair = qnameDAO.getQName(nodeTypeQNameId); | ||||
|   | ||||
| @@ -37,7 +37,6 @@ | ||||
|                 <property name="properties" ref="global-properties" /> | ||||
|             </bean> | ||||
|         </property> | ||||
|         <property name="auditRecordReporter" ref="auditRecordReporter"/> | ||||
|     </bean> | ||||
|      | ||||
|     <!-- User Audit Filter --> | ||||
| @@ -110,7 +109,4 @@ | ||||
|     <!-- Reference in the audit registry managed bean --> | ||||
|     <alias name="Audit" alias="auditModel.modelRegistry"/> | ||||
|        | ||||
|     <!-- Audit Record Reported --> | ||||
|     <bean id="auditRecordReporter" class="org.alfresco.repo.audit.AuditRecordReporterImpl"/> | ||||
|  | ||||
| </beans> | ||||
| @@ -133,14 +133,6 @@ | ||||
|     <resultMap id="result_FilterSortNode" type="FilterSortNode"> | ||||
|          | ||||
|         <id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|         <result property="nodeUuid" column="uuid" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="typeQNameId" column="type_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|  | ||||
|         <result property="auditablePropertiesEntity.auditCreator" column="audit_creator" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="auditablePropertiesEntity.auditCreated" column="audit_created" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="auditablePropertiesEntity.auditModifier" column="audit_modifier" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="auditablePropertiesEntity.auditModified" column="audit_modified" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="auditablePropertiesEntity.auditAccessed" column="audit_accessed" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|          | ||||
|         <result property="prop1.nodeId" column="prop1_node_id" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
|         <result property="prop1.key.qnameId" column="prop1_qname_id" jdbcType="BIGINT" javaType="java.lang.Long"/> | ||||
| @@ -178,8 +170,8 @@ | ||||
|         <result property="prop3.value.doubleValue" column="prop3_double_value" jdbcType="FLOAT" javaType="java.lang.Double"/> | ||||
|         <result property="prop3.value.stringValue" column="prop3_string_value" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|          | ||||
|         <result property="storeProtocol" column="protocol" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <result property="storeIdentifier" column="identifier" jdbcType="VARCHAR" javaType="java.lang.String"/> | ||||
|         <association property="node" resultMap="alfresco.node.result_Node"/> | ||||
|          | ||||
|     </resultMap> | ||||
|      | ||||
|     <resultMap id="result_ArchivedNodes" type="ArchivedNodes"> | ||||
| @@ -980,8 +972,8 @@ | ||||
|     </select> | ||||
|  | ||||
|     <!-- GetChildren - with explicit prop filtering and/or sorting --> | ||||
|     <select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode" flushCache="true"> | ||||
|        select distinct | ||||
|     <select id="select_GetChildrenCannedQueryWithProps" parameterType="FilterSortNode" resultMap="result_FilterSortNode"> | ||||
|        select | ||||
|             childNode.id             as id, | ||||
|             childNode.version        as version, | ||||
|             childStore.id            as store_id, | ||||
| @@ -1075,6 +1067,9 @@ | ||||
|                     #{item} | ||||
|                 </foreach> | ||||
|             </if> | ||||
|         <if test="prop1qnameId == null and auditableProps == false"> | ||||
|             <include refid="alfresco.node.select_ChildAssoc_OrderBy"/> | ||||
|         </if> | ||||
|     </select> | ||||
|      | ||||
|     <!-- GetChildren - with no explicit sorting (or prop filtering) - note: still filtered by child type (and optionally primary or secondary) --> | ||||
|   | ||||
| @@ -286,8 +286,6 @@ audit.alfresco-access.enabled=false | ||||
| audit.alfresco-access.sub-actions.enabled=false | ||||
| audit.cmischangelog.enabled=false | ||||
| audit.dod5015.enabled=false | ||||
| audit.enabled.auditingToAuditStorage=false | ||||
| audit.enabled.auditingToDatabase=true | ||||
| # Setting this flag to true will force startup failure when invalid audit configurations are detected | ||||
| audit.config.strict=false | ||||
| # Audit map filter for AccessAuditor - restricts recorded events to user driven events  | ||||
|   | ||||
| @@ -48,7 +48,6 @@ import org.alfresco.util.testing.category.NonBuildTests; | ||||
|         org.alfresco.repo.audit.UserAuditFilterTest.class, | ||||
|         org.alfresco.repo.audit.AuditMethodInterceptorTest.class, | ||||
|         org.alfresco.repo.audit.access.AccessAuditorTest.class, | ||||
|         org.alfresco.repo.audit.AuditRecordUtilsTest.class, | ||||
|  | ||||
|         // the following test will lock up the DB if run in the applicationContext_01 test suite | ||||
|         org.alfresco.repo.activities.feed.FeedNotifierTest.class, | ||||
|   | ||||
| @@ -877,7 +877,6 @@ public class AuditComponentTest extends TestCase | ||||
|         auditModelRegistry.loadAuditModels(); | ||||
|  | ||||
|         auditModelRegistry.setProperty("audit.enabled", "true"); | ||||
|         auditModelRegistry.setProperty("audit.enabled.auditingToDatabase", "true"); | ||||
|  | ||||
|         auditModelRegistry.setProperty("audit.app1.enabled", "true"); | ||||
|         auditModelRegistry.setProperty("audit.filter.app1.default.enabled", "true"); | ||||
|   | ||||
| @@ -1,123 +0,0 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 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.repo.audit; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.Instant; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import org.junit.Test; | ||||
|  | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.namespace.QName; | ||||
|  | ||||
| public class AuditRecordUtilsTest | ||||
| { | ||||
|     @SuppressWarnings("unchecked") | ||||
|     @Test | ||||
|     public void testGenerateAuditRecordBuilderTest() | ||||
|     { | ||||
|         var testData = new HashMap<String, Serializable>(); | ||||
|  | ||||
|         testData.put("/alfresco-access/transaction/path", "/app:company_home"); | ||||
|         testData.put("/alfresco-access/transaction/user", "admin"); | ||||
|         testData.put("/alfresco-access/transaction/sub-actions", "updateNodeProperties"); | ||||
|         var now = Instant.now(); | ||||
|         testData.put("/alfresco-access/transaction/properties/from", (Serializable) Map.of(QName.createQName("modified"), Date.from(now))); | ||||
|         testData.put("/alfresco-access/transaction/properties/to", (Serializable) Map.of(QName.createQName("modified"), Date.from(now))); | ||||
|  | ||||
|         var builder = AuditRecordUtils.generateAuditRecordBuilder(testData, "/alfresco-access/".length()); | ||||
|         builder.setAuditRecordType("alfresco-access"); | ||||
|         var auditRecord = builder.build(); | ||||
|  | ||||
|         assertNotNull(auditRecord); | ||||
|         assertEquals("alfresco-access", auditRecord.getAuditApplicationId()); | ||||
|  | ||||
|         var auditData = auditRecord.getAuditData(); | ||||
|         assertEquals(1, auditData.size()); | ||||
|  | ||||
|         var transaction = (HashMap<String, ?>) auditData.get("transaction"); | ||||
|         assertNotNull(transaction); | ||||
|         assertEquals(4, transaction.size()); | ||||
|         assertEquals(testData.get("/alfresco-access/transaction/path"), transaction.get("path")); | ||||
|         assertEquals(testData.get("/alfresco-access/transaction/user"), transaction.get("user")); | ||||
|         assertEquals(testData.get("/alfresco-access/transaction/sub-actions"), transaction.get("sub-actions")); | ||||
|  | ||||
|         var properties = (HashMap<String, Object>) transaction.get("properties"); | ||||
|         assertNotNull(properties); | ||||
|         assertEquals(2, properties.size()); | ||||
|         assertEquals(testData.get("/alfresco-access/transaction/properties/from"), properties.get("from")); | ||||
|         assertEquals(testData.get("/alfresco-access/transaction/properties/to"), properties.get("to")); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("unchecked") | ||||
|     @Test | ||||
|     public void testGenerateAuditRecordBuilderTestNodeRef() | ||||
|     { | ||||
|         var testData = new HashMap<String, Serializable>(); | ||||
|         var expectedValue = new HashMap<String, Serializable>(); | ||||
|  | ||||
|         expectedValue.put("nodeRef", new NodeRef("workspace://SpacesStore/bfa612e6-1a02-46a0-a612-e61a02e6a036")); | ||||
|         expectedValue.put("objectId", "bfa612e6-1a02-46a0-a612-e61a02e6a036;1.0"); | ||||
|  | ||||
|         testData.put("/CMISChangeLog/CREATED/result/value", expectedValue); | ||||
|  | ||||
|         var builder = AuditRecordUtils.generateAuditRecordBuilder(testData, "/CMISChangeLog/".length()); | ||||
|         builder.setAuditRecordType("CMISChangeLog"); | ||||
|         var auditRecord = builder.build(); | ||||
|  | ||||
|         assertNotNull(auditRecord); | ||||
|  | ||||
|         assertEquals("CMISChangeLog", auditRecord.getAuditApplicationId()); | ||||
|  | ||||
|         var auditData = auditRecord.getAuditData(); | ||||
|         assertEquals(1, auditData.size()); | ||||
|  | ||||
|         var created = (HashMap<String, ?>) auditData.get("CREATED"); | ||||
|         assertNotNull(created); | ||||
|  | ||||
|         assertEquals(1, created.size()); | ||||
|         var result = (HashMap<String, Object>) created.get("result"); | ||||
|         assertNotNull(result); | ||||
|         assertEquals(1, result.size()); | ||||
|  | ||||
|         var resultValue = (HashMap<String, Object>) result.get("value"); | ||||
|         assertNotNull(resultValue); | ||||
|         assertEquals(2, resultValue.size()); | ||||
|  | ||||
|         var expectedNodeRef = (NodeRef) expectedValue.get("nodeRef"); | ||||
|         assertEquals(expectedNodeRef.getId(), resultValue.get("nodeRef")); | ||||
|         assertEquals(expectedValue.get("objectId"), resultValue.get("objectId")); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -50,7 +50,6 @@ public class AuditTestSuite extends TestSuite | ||||
|         suite.addTestSuite(UserAuditFilterTest.class); | ||||
|         suite.addTestSuite(AuditMethodInterceptorTest.class); | ||||
|  | ||||
|         suite.addTest(new JUnit4TestAdapter(AuditRecordUtilsTest.class)); | ||||
|         suite.addTest(new JUnit4TestAdapter(PropertyAuditFilterTest.class)); | ||||
|         suite.addTest(new JUnit4TestAdapter(AccessAuditorTest.class)); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user