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.43
			...
			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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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)
 | 
			
		||||
   {
 | 
			
		||||
 
 | 
			
		||||
@@ -233,15 +233,15 @@ var Filters =
 | 
			
		||||
            filterParams.query = "+ID:\"" + parsedArgs.nodeRef + "\"";
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          case "tag":
 | 
			
		||||
              // Remove any trailing "/" character
 | 
			
		||||
              if (filterData.charAt(filterData.length - 1) == "/")
 | 
			
		||||
              {
 | 
			
		||||
                  filterData = filterData.slice(0, -1);
 | 
			
		||||
              }
 | 
			
		||||
              filterQuery = this.constructPathQuery(parsedArgs);
 | 
			
		||||
              filterParams.query = filterQuery + " +TAG:\"" + search.ISO9075Encode(filterData) + "\"";
 | 
			
		||||
              break;
 | 
			
		||||
         case "tag":
 | 
			
		||||
            // Remove any trailing "/" character
 | 
			
		||||
            if (filterData.charAt(filterData.length - 1) == "/")
 | 
			
		||||
            {
 | 
			
		||||
               filterData = filterData.slice(0, -1);
 | 
			
		||||
            }
 | 
			
		||||
            filterQuery = this.constructPathQuery(parsedArgs);
 | 
			
		||||
            filterParams.query = filterQuery + " +PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(filterData) + "/member\"";
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
         case "category":
 | 
			
		||||
            // Remove any trailing "/" character
 | 
			
		||||
@@ -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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</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.43</version>
 | 
			
		||||
        <version>25.3.0.33-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								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.43</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,10 +51,10 @@
 | 
			
		||||
        <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.9</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.8</dependency.spring.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.43</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.43</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.43</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
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,9 +37,8 @@
 | 
			
		||||
                <property name="properties" ref="global-properties" />
 | 
			
		||||
            </bean>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="auditRecordReporter" ref="auditRecordReporter"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    <!-- User Audit Filter -->
 | 
			
		||||
    
 | 
			
		||||
    <bean id="userAuditFilter" class="org.alfresco.repo.audit.UserAuditFilter">
 | 
			
		||||
@@ -109,8 +108,5 @@
 | 
			
		||||
   
 | 
			
		||||
    <!-- 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>
 | 
			
		||||
      
 | 
			
		||||
</beans>
 | 
			
		||||
@@ -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