mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	Compare commits
	
		
			395 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 6baafc0e88 | ||
|  | b1cf78ce7c | ||
|  | a2f9857442 | ||
|  | 8c69432052 | ||
|  | 124f87ee21 | ||
|  | 3cd3b2c2d6 | ||
|  | 14da8d2002 | ||
|  | 6a4bbb021c | ||
|  | 42d70b17c7 | ||
|  | c7eba0ddc8 | ||
|  | 266094c0e1 | ||
|  | e442b4acf0 | ||
|  | fd1028a685 | ||
|  | 0a7e275a9c | ||
|  | d1bbba7286 | ||
|  | e1baddebee | ||
|  | 3263dcaf2f | ||
|  | 8926f7f9a7 | ||
|  | 764a1b656c | ||
|  | cf265f2dea | ||
|  | fd0d5204eb | ||
|  | f9b8a4b42d | ||
|  | fcdc1438e7 | ||
|  | 7cd1416561 | ||
|  | f197757f94 | ||
|  | af995f1087 | ||
|  | 2cfcd3dfa7 | ||
|  | 89e09b0162 | ||
|  | 495808b172 | ||
|  | 57060af84b | ||
|  | 60261aafd1 | ||
|  | 8dad225394 | ||
|  | 5cc21c55e7 | ||
|  | c71aaf7537 | ||
|  | b7d16ac915 | ||
|  | 1a436b06e4 | ||
|  | be02be5a8b | ||
|  | a674e574c5 | ||
|  | aacaa62ff9 | ||
|  | 371bd1543d | ||
|  | 4cb16f046f | ||
|  | 2fb7de9ace | ||
|  | ed972c79d7 | ||
|  | 0f3e2dc4cc | ||
|  | 4e7d0ccae3 | ||
|  | 1b5636a339 | ||
|  | 164ce720af | ||
|  | 258738e3dd | ||
|  | fefd937c89 | ||
|  | 91f9467a99 | ||
|  | 97b1515f7c | ||
|  | 7f235f1e2b | ||
|  | 109bdeee0f | ||
|  | 7c97f49574 | ||
|  | 2088b8b553 | ||
|  | 280a873cb6 | ||
|  | 9683c18448 | ||
|  | 21b36a7100 | ||
|  | 96481daae1 | ||
|  | 7ef573699b | ||
|  | a000df7ceb | ||
|  | 4a22735120 | ||
|  | 94d84799be | ||
|  | 754776e30c | ||
|  | 28b8bb85e4 | ||
|  | 4910028d51 | ||
|  | 75d0825295 | ||
|  | 964cedaebd | ||
|  | 2bda7d7231 | ||
|  | 82d316d802 | ||
|  | 1840d1056d | ||
|  | 334e8c84df | ||
|  | 24309cf4b6 | ||
|  | 2d28742a94 | ||
|  | d6503ac1de | ||
|  | 73ef1ed9ff | ||
|  | d3bc9e2b60 | ||
|  | 174186d1ff | ||
|  | 57331afe8f | ||
|  | 7c87595b0c | ||
|  | b7191b175e | ||
|  | 39b19d1ceb | ||
|  | 9e23b99078 | ||
|  | ac36ac07e8 | ||
|  | cc10339577 | ||
|  | 8aa975fbc3 | ||
|  | 01620b75ff | ||
|  | 9327218f17 | ||
|  | b57373fbe3 | ||
|  | 613fb458b9 | ||
|  | 31cd97b9d2 | ||
|  | 255fe46c8e | ||
|  | 88d32748b1 | ||
|  | 90e1522a56 | ||
|  | 7e61befc21 | ||
|  | be6dc14330 | ||
|  | ab4bc1af9f | ||
|  | eaec23ae7a | ||
|  | 8ff727c95d | ||
|  | 48475fdfaa | ||
|  | 812959be2e | ||
|  | 5b8c52db67 | ||
|  | 20c42b6561 | ||
|  | 52dfea9b21 | ||
|  | d04dada44e | ||
|  | 2e85de7c81 | ||
|  | 42324368e5 | ||
|  | 8d885220d8 | ||
|  | 6367f5304d | ||
|  | f17b309c27 | ||
|  | bb2cc1765d | ||
|  | d20e8ee158 | ||
|  | 254193f9aa | ||
|  | 4293f21618 | ||
|  | e0eb43c479 | ||
|  | f1bbb6cce7 | ||
|  | e6e2a2d8ac | ||
|  | c2cfcdc35a | ||
|  | 6b2ac86b1d | ||
|  | 8b212dc4cf | ||
|  | e2c357c1e0 | ||
|  | 4a024e510d | ||
|  | 3f75c9b15f | ||
|  | 96f94a98be | ||
|  | bfc0445aeb | ||
|  | 977f6f12d4 | ||
|  | 626640ddc7 | ||
|  | 2b00e550a9 | ||
|  | f3dca482ff | ||
|  | 94e957cb73 | ||
|  | 8868e64a6a | ||
|  | f4af65943f | ||
|  | 6fe1b50741 | ||
|  | f300bd6b3a | ||
|  | f7195ef16a | ||
|  | ef228f0614 | ||
|  | 6c0f231316 | ||
|  | 33b521b421 | ||
|  | eff4e0738c | ||
|  | 5685fc3b17 | ||
|  | 7c22a2598b | ||
|  | efe053167d | ||
|  | 4aae383637 | ||
|  | ca1774ffae | ||
|  | 6206f67bdd | ||
|  | 82897f449f | ||
|  | e6d30cddac | ||
|  | 0e6b444a25 | ||
|  | 61dc54bb33 | ||
|  | a6c7f044df | ||
|  | 18016df074 | ||
|  | b021c1ebfe | ||
|  | e3e42137d9 | ||
|  | 9327814266 | ||
|  | d45fd10431 | ||
|  | 09242daaec | ||
|  | 491a41e8ba | ||
|  | 1dac1e5fdb | ||
|  | 2c9d8e63ea | ||
|  | a3998de1ba | ||
|  | 582742bbd3 | ||
|  | ebe29717fa | ||
|  | c6a654cbcf | ||
|  | cd947b5581 | ||
|  | ef4dd74580 | ||
|  | 7edbdd72f2 | ||
|  | b7978c2a62 | ||
|  | c1d9142a9c | ||
|  | 03a5a3cd3a | ||
|  | c1ac217c44 | ||
|  | 1b04fef8cd | ||
|  | 31bb692b16 | ||
|  | 3222f13efe | ||
|  | d66ed689a0 | ||
|  | f84a7035d7 | ||
|  | 56177b6790 | ||
|  | 3c32899f6e | ||
|  | d3512dd8e4 | ||
|  | d8273b19cf | ||
|  | 8abea08762 | ||
|  | 42e3ead101 | ||
|  | b1c095b51e | ||
|  | ab85ea8ffe | ||
|  | 9a794cfe97 | ||
|  | 8e3f610f8a | ||
|  | 8c9edde95f | ||
|  | 5652317a0a | ||
|  | b8a9a9588c | ||
|  | a48cf7eed3 | ||
|  | 73f6c7a8f7 | ||
|  | 37aaa0d147 | ||
|  | 5d5d1d8680 | ||
|  | 120d4acdb0 | ||
|  | fa3acb47a9 | ||
|  | 716b039c07 | ||
|  | abec95881e | ||
|  | 58164d59bf | ||
|  | 8e80b87439 | ||
|  | 4e3591cc72 | ||
|  | 6aa4c37825 | ||
|  | 68dae275a5 | ||
|  | 536f8c609c | ||
|  | 6686863352 | ||
|  | 3774a0e504 | ||
|  | 4bf569d297 | ||
|  | 13bcfe4125 | ||
|  | 982e0d24f5 | ||
|  | c2fbf53b03 | ||
|  | f8b5e9cb03 | ||
|  | ea0b37022b | ||
|  | f20a9b441d | ||
|  | 7c3a9113a0 | ||
|  | 66d9beef14 | ||
|  | 4a97305505 | ||
|  | 9b4593e4b3 | ||
|  | 01a2a23c4a | ||
|  | 2c2b51f47e | ||
|  | 1e37b3308d | ||
|  | 84a36d68d4 | ||
|  | 40d475abf9 | ||
|  | 5d3f1f2402 | ||
|  | 2cd29d87ec | ||
|  | 8f1631fb55 | ||
|  | 5f6dced886 | ||
|  | 25fdc9ccc7 | ||
|  | b6456cde34 | ||
|  | 27b80d8adb | ||
|  | 536e12ff76 | ||
|  | 96ab699ea8 | ||
|  | 9630d4cb02 | ||
|  | fe9175d959 | ||
|  | 277d10133d | ||
|  | 3fb964a460 | ||
|  | d630dcb7af | ||
|  | 7a673966aa | ||
|  | 65d2863b9d | ||
|  | 56ef484ae0 | ||
|  | d619d5365e | ||
|  | 7096276b02 | ||
|  | c9a46e1a8a | ||
|  | 98f9175a13 | ||
|  | 4e89b0a033 | ||
|  | c6c0779984 | ||
|  | 554b26e7e7 | ||
|  | 93d704d44c | ||
|  | 0916efad7c | ||
|  | 6169ec0095 | ||
|  | 75ace2a268 | ||
|  | f489c4193b | ||
|  | 71c3addf2d | ||
|  | cc43f9338e | ||
|  | 45ad5045b1 | ||
|  | 773f99453e | ||
|  | 538d269f66 | ||
|  | 1dbf1c1314 | ||
|  | 3969cd8f14 | ||
|  | eaa11fcb34 | ||
|  | cd5c2227e2 | ||
|  | 757b26b1b8 | ||
|  | 0366449457 | ||
|  | 6827b2c7a1 | ||
|  | 36bc1dc1a4 | ||
|  | 8407159a17 | ||
|  | 917dd35c27 | ||
|  | 6e815ebd34 | ||
|  | ad0668cce3 | ||
|  | 11fd7ca1dd | ||
|  | 6be0c3031f | ||
|  | a1d869bdef | ||
|  | d130c12f2a | ||
|  | 24e987e735 | ||
|  | 63e7492823 | ||
|  | 545a957a1b | ||
|  | 325e980cf0 | ||
|  | e2a4dcc6ad | ||
|  | a993c9ed97 | ||
|  | 85d2a5176b | ||
|  | 3c245ae64c | ||
|  | fbf5966d10 | ||
|  | 8fca14df40 | ||
|  | e38e7b4bda | ||
|  | b378de58d8 | ||
|  | 8a64d9fb0b | ||
|  | 3c092b696d | ||
|  | 6f222106c5 | ||
|  | bd5a016382 | ||
|  | dc24718717 | ||
|  | e65614d3c2 | ||
|  | 698f9b15ce | ||
|  | 09a254e5fd | ||
|  | 6f442a703a | ||
|  | f1862c9636 | ||
|  | 231075fd5e | ||
|  | 979420879c | ||
|  | db330e28f5 | ||
|  | bae0573636 | ||
|  | 8089fc2572 | ||
|  | 1c4fe53c0f | ||
|  | 7a8aa1a2c1 | ||
|  | e08ba1fd4f | ||
|  | 4f40bd0687 | ||
|  | a3578f7baa | ||
|  | 8e8b9c868f | ||
|  | f77b3b79e5 | ||
|  | 3a7157f4a7 | ||
|  | d6b979f341 | ||
|  | a090de4e71 | ||
|  | 03621db30a | ||
|  | 766a6def2b | ||
|  | 117804fb68 | ||
|  | f03e6761ce | ||
|  | 74c8288206 | ||
|  | c0bd0a680b | ||
|  | 8645cdc76d | ||
|  | 5055eec2df | ||
|  | 892f41d6fd | ||
|  | 075b02baee | ||
|  | 7c8a75ce6c | ||
|  | cb0a925e27 | ||
|  | c7d2699f7e | ||
|  | b942b55193 | ||
|  | c1100fe983 | ||
|  | 62236c90f5 | ||
|  | eabdab91fb | ||
|  | 4f83076cfe | ||
|  | 7eda1d420f | ||
|  | 411388d62d | ||
|  | 245d1317ac | ||
|  | ee5e34ca32 | ||
|  | c4dcef73e1 | ||
|  | 4f53fee1fc | ||
|  | d163410e3d | ||
|  | 9ca251edba | ||
|  | 193cb9b30d | ||
|  | e9a36f67fe | ||
|  | c18a58caea | ||
|  | 11659ab917 | ||
|  | 89b1049809 | ||
|  | 192c105719 | ||
|  | b8fc8efa07 | ||
|  | 2e851cf88d | ||
|  | ebf081c731 | ||
|  | b979701264 | ||
|  | aa0d02abf2 | ||
|  | 2f7b8d50a3 | ||
|  | 800736a025 | ||
|  | b8b7e5193e | ||
|  | 808faa71b3 | ||
|  | 0bd476968b | ||
|  | e51e5e8ca5 | ||
|  | 46db14d5ff | ||
|  | b5fa73ca3b | ||
|  | c962daae3b | ||
|  | 8efc559b09 | ||
|  | 08628732fc | ||
|  | 7f74bf7b3e | ||
|  | 390073b153 | ||
|  | 68c87f69c5 | ||
|  | 2b936050c8 | ||
|  | 28184ca69a | ||
|  | e05c74813e | ||
|  | e05a1d9ba9 | ||
|  | 5aab15a77a | ||
|  | 5d267c8d60 | ||
|  | 18fc9a58b4 | ||
|  | 6a7ba876b7 | ||
|  | 65bdb242ec | ||
|  | 5a537b301a | ||
|  | 515b894241 | ||
|  | 4978d9e790 | ||
|  | bf8f5117ac | ||
|  | cfb5cb2c6d | ||
|  | 71eed6822d | ||
|  | b1fe69693c | ||
|  | 56d415fe4c | ||
|  | 8f4e617703 | ||
|  | d8bdb82291 | ||
|  | f2927a804e | ||
|  | baba2090a8 | ||
|  | dbb1bc11f4 | ||
|  | 9b53abdc98 | ||
|  | 58bff2bebf | ||
|  | 157430c0d6 | ||
|  | 9cddeb61c8 | ||
|  | 86980cb634 | ||
|  | 72fed7f913 | ||
|  | 13a83d9e22 | ||
|  | a2735539ea | ||
|  | 1cb3931f21 | ||
|  | 0f5653e250 | ||
|  | 4a33ad8c3b | ||
|  | 85703f4284 | ||
|  | 127912aca9 | ||
|  | 70135ab771 | ||
|  | fa516ef58f | 
							
								
								
									
										795
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										795
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										20
									
								
								.github/workflows/master_release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/master_release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -31,15 +31,15 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[no release]') && | ||||
|       github.event_name != 'pull_request' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: actions/checkout@v5 | ||||
|         with: | ||||
|           persist-credentials: false | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.16.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 | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.24.1 | ||||
|         with: | ||||
|           username: ${{ env.GIT_USERNAME }} | ||||
|           email: ${{ env.GIT_EMAIL }} | ||||
| @@ -60,15 +60,15 @@ jobs: | ||||
|       !contains(github.event.head_commit.message, '[no downstream]') && | ||||
|       github.event_name != 'pull_request' | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: actions/checkout@v5 | ||||
|         with: | ||||
|           persist-credentials: false | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.16.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 | ||||
|       - name: "Init" | ||||
|         run: bash ./scripts/ci/init.sh | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v8.24.1 | ||||
|         with: | ||||
|           username: ${{ env.GIT_USERNAME }} | ||||
|           email: ${{ env.GIT_EMAIL }} | ||||
|   | ||||
							
								
								
									
										6
									
								
								.github/workflows/precommit_formatter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/precommit_formatter.yml
									
									
									
									
										vendored
									
									
								
							| @@ -11,9 +11,9 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     if: contains(github.event.head_commit.message, '[reformat code]') | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: actions/checkout@v5 | ||||
|       - name: Set up Python ${{ inputs.python-version }} | ||||
|         uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 | ||||
|         uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | ||||
|         with: | ||||
|           python-version: "3.9" | ||||
|       - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 | ||||
| @@ -22,7 +22,7 @@ jobs: | ||||
|           extra_args: --all-files | ||||
|       - name: Update secrets baseline | ||||
|         run: pip install detect-secrets && detect-secrets scan --baseline .secrets.baseline | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@v8.16.0 | ||||
|       - uses: Alfresco/alfresco-build-tools/.github/actions/git-commit-changes@v8.24.1 | ||||
|         with: | ||||
|           username: ${{ secrets.BOT_GITHUB_USERNAME }} | ||||
|           add-options: -u | ||||
|   | ||||
| @@ -127,29 +127,6 @@ | ||||
|     } | ||||
|   ], | ||||
|   "results": { | ||||
|     ".github/workflows/ci.yml": [ | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "b86dc2f033a63f2b7b9e7d270ab806d2910d7572", | ||||
|         "is_verified": false, | ||||
|         "line_number": 295 | ||||
|       }, | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "1bfb0e20f886150ba59b853bcd49dea893e00966", | ||||
|         "is_verified": false, | ||||
|         "line_number": 370 | ||||
|       }, | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
|         "filename": ".github/workflows/ci.yml", | ||||
|         "hashed_secret": "128f14373ccfaff49e3664045d3a11b50cbb7b39", | ||||
|         "is_verified": false, | ||||
|         "line_number": 904 | ||||
|       } | ||||
|     ], | ||||
|     ".github/workflows/master_release.yml": [ | ||||
|       { | ||||
|         "type": "Secret Keyword", | ||||
| @@ -1265,7 +1242,7 @@ | ||||
|         "filename": "repository/src/main/resources/alfresco/repository.properties", | ||||
|         "hashed_secret": "1459a56410378e4d3ab470eff570e5eae1742762", | ||||
|         "is_verified": false, | ||||
|         "line_number": 312, | ||||
|         "line_number": 314, | ||||
|         "is_secret": false | ||||
|       }, | ||||
|       { | ||||
| @@ -1273,7 +1250,7 @@ | ||||
|         "filename": "repository/src/main/resources/alfresco/repository.properties", | ||||
|         "hashed_secret": "84551ae5442affc9f1a2d3b4c86ae8b24860149d", | ||||
|         "is_verified": false, | ||||
|         "line_number": 770, | ||||
|         "line_number": 773, | ||||
|         "is_secret": false | ||||
|       } | ||||
|     ], | ||||
| @@ -1868,5 +1845,5 @@ | ||||
|       } | ||||
|     ] | ||||
|   }, | ||||
|   "generated_at": "2025-03-27T23:45:41Z" | ||||
|   "generated_at": "2025-07-23T08:25:11Z" | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-automation-community-repo</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <build> | ||||
| @@ -74,16 +74,6 @@ | ||||
|          <artifactId>alfresco-testng</artifactId> | ||||
|          <version>1.1</version> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.squareup.okhttp3</groupId> | ||||
|          <artifactId>okhttp</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.awaitility</groupId> | ||||
|          <artifactId>awaitility</artifactId> | ||||
| @@ -93,7 +83,7 @@ | ||||
|       <dependency> | ||||
|          <groupId>org.apache.commons</groupId> | ||||
|          <artifactId>commons-collections4</artifactId> | ||||
|          <version>4.4</version> | ||||
|          <version>4.5.0</version> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.github.docker-java</groupId> | ||||
|   | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model; | ||||
|  | ||||
| public record CapabilityModel(String name, String title, String description, GroupModel group, int index) | ||||
| {} | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model; | ||||
|  | ||||
| public record GroupModel(String id, String title) | ||||
| {} | ||||
| @@ -0,0 +1,91 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import org.alfresco.rest.rm.community.model.CapabilityModel; | ||||
| import org.alfresco.utility.model.TestModel; | ||||
|  | ||||
| /** | ||||
|  * POJO for role | ||||
|  */ | ||||
| @Builder | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class Role extends TestModel | ||||
| { | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String name; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private List<CapabilityModel> capabilities; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String displayLabel; | ||||
|  | ||||
|     @JsonProperty(required = true) | ||||
|     private String groupShortName; | ||||
|  | ||||
|     private List<String> assignedUsers; | ||||
|  | ||||
|     private List<String> assignedGroups; | ||||
|  | ||||
|     private String roleGroupName; | ||||
|  | ||||
|     @Override | ||||
|     public boolean equals(Object o) | ||||
|     { | ||||
|         if (this == o) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         if (o == null || getClass() != o.getClass()) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         Role role = (Role) o; | ||||
|         return Objects.equals(name, role.name) && Objects.equals(capabilities, role.capabilities) | ||||
|                 && Objects.equals(displayLabel, role.displayLabel) && Objects.equals(groupShortName, role.groupShortName) && Objects.equals(assignedUsers, role.assignedUsers) | ||||
|                 && Objects.equals(assignedGroups, role.assignedGroups) && Objects.equals(roleGroupName, role.roleGroupName); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int hashCode() | ||||
|     { | ||||
|         return Objects.hash(name, capabilities, displayLabel, groupShortName, assignedUsers, assignedGroups, roleGroupName); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import org.alfresco.rest.core.RestModels; | ||||
|  | ||||
| public class RoleCollection extends RestModels<RoleEntry, RoleCollection> | ||||
| {} | ||||
| @@ -0,0 +1,47 @@ | ||||
| /*- | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rest.rm.community.model.role; | ||||
|  | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import org.alfresco.rest.core.RestModels; | ||||
|  | ||||
| @Builder | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @NoArgsConstructor | ||||
| @AllArgsConstructor | ||||
| public class RoleEntry extends RestModels<Role, RoleEntry> | ||||
| { | ||||
|     @JsonProperty | ||||
|     private Role entry; | ||||
| } | ||||
| @@ -35,7 +35,7 @@ package org.alfresco.rest.rm.community.model.user; | ||||
|  */ | ||||
| public enum UserRoles | ||||
| { | ||||
|     IN_PLACE_WRITERS("ExtendedWriters", "In-Place Writers"), ROLE_RM_ADMIN("Administrator", "Records Management Administrator"), ROLE_RM_MANAGER("RecordsManager", "Records Management Manager"), ROLE_RM_POWER_USER("PowerUser", "Records Management Power User"), ROLE_RM_SECURITY_OFFICER("SecurityOfficer", "Records Management Security Officer"), ROLE_RM_USER("User", "Records Management User"); | ||||
|     IN_PLACE_WRITERS("ExtendedWriters", "In-Place Writers"), ROLE_RM_ADMIN("Administrator", "Records Management Administrator"), ROLE_RM_MANAGER("RecordsManager", "Records Management Manager"), ROLE_RM_POWER_USER("PowerUser", "Records Management Power User"), ROLE_RM_SECURITY_OFFICER("SecurityOfficer", "Records Management Security Officer"), ROLE_RM_USER("User", "Records Management User"), IN_PLACE_READERS("ExtendedReaders", "In-Place Readers"); | ||||
|  | ||||
|     public final String roleId; | ||||
|     public final String displayName; | ||||
|   | ||||
| @@ -43,6 +43,7 @@ import org.alfresco.rest.rm.community.model.hold.Hold; | ||||
| import org.alfresco.rest.rm.community.model.hold.HoldCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection; | ||||
| import org.alfresco.rest.rm.community.model.role.RoleCollection; | ||||
| import org.alfresco.rest.rm.community.requests.RMModelRequest; | ||||
|  | ||||
| /** | ||||
| @@ -303,4 +304,39 @@ public class FilePlanAPI extends RMModelRequest | ||||
|     { | ||||
|         return getHolds(filePlanId, EMPTY); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the roles of a file plan. | ||||
|      * | ||||
|      * @param filePlanId | ||||
|      *            The identifier of a file plan | ||||
|      * @param parameters | ||||
|      *            The URL parameters to add | ||||
|      * @return The {Pagination and RoleModel Entries} for the given {@code filePlanId} | ||||
|      * @throws RuntimeException | ||||
|      *             for the following cases: | ||||
|      *             <ul> | ||||
|      *             <li>authentication fails</li> | ||||
|      *             <li>current user does not have permission to read {@code filePlanId}</li> | ||||
|      *             <li>{@code filePlanId} does not exist</li> | ||||
|      *             </ul> | ||||
|      */ | ||||
|     public RoleCollection getFilePlanRoles(String filePlanId, String parameters) | ||||
|     { | ||||
|         mandatoryString("filePlanId", filePlanId); | ||||
|         return getRmRestWrapper().processModels(RoleCollection.class, simpleRequest( | ||||
|                 GET, | ||||
|                 "file-plans/{filePlanId}/roles?{parameters}", | ||||
|                 filePlanId, | ||||
|                 parameters)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * See {@link #getFilePlanRoles(String, String)} | ||||
|      */ | ||||
|     public RoleCollection getFilePlanRoles(String filePlanId) | ||||
|     { | ||||
|         return getFilePlanRoles(filePlanId, EMPTY); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -43,7 +43,7 @@ import com.github.dockerjava.core.command.LogContainerResultCallback; | ||||
| import com.github.dockerjava.netty.NettyDockerCmdExecFactory; | ||||
| import lombok.Getter; | ||||
| import lombok.Setter; | ||||
| import org.apache.commons.lang.SystemUtils; | ||||
| import org.apache.commons.lang3.SystemUtils; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
|   | ||||
| @@ -93,6 +93,7 @@ import org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI; | ||||
| import org.alfresco.rest.search.RestRequestQueryModel; | ||||
| import org.alfresco.rest.search.SearchNodeModel; | ||||
| import org.alfresco.rest.search.SearchRequest; | ||||
| import org.alfresco.rest.v0.RMRolesAndActionsAPI; | ||||
| import org.alfresco.rest.v0.SearchAPI; | ||||
| import org.alfresco.utility.Utility; | ||||
| import org.alfresco.utility.data.DataUserAIS; | ||||
| @@ -127,6 +128,10 @@ public class BaseRMRestTest extends RestTest | ||||
|     @Getter(value = PROTECTED) | ||||
|     private SearchAPI searchApi; | ||||
|  | ||||
|     @Autowired | ||||
|     @Getter(PROTECTED) | ||||
|     private RMRolesAndActionsAPI rmRolesAndActionsV0API; | ||||
|  | ||||
|     protected static final String iso8601_DateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -28,6 +28,7 @@ package org.alfresco.rest.rm.community.fileplans; | ||||
|  | ||||
| import static java.util.Arrays.asList; | ||||
|  | ||||
| import static com.google.common.collect.Sets.newHashSet; | ||||
| import static org.springframework.http.HttpStatus.CONFLICT; | ||||
| import static org.springframework.http.HttpStatus.CREATED; | ||||
| import static org.springframework.http.HttpStatus.FORBIDDEN; | ||||
| @@ -56,19 +57,27 @@ import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanCo | ||||
| import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_CONTAINER_TYPE; | ||||
| import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.IN_PLACE_READERS; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.IN_PLACE_WRITERS; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_ADMIN; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_MANAGER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_POWER_USER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_SECURITY_OFFICER; | ||||
| import static org.alfresco.rest.rm.community.model.user.UserRoles.ROLE_RM_USER; | ||||
| import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric; | ||||
| import static org.alfresco.utility.data.RandomData.getRandomName; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.NoSuchElementException; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.testng.annotations.DataProvider; | ||||
| import org.testng.annotations.Test; | ||||
|  | ||||
| import org.alfresco.rest.rm.community.base.BaseRMRestTest; | ||||
| import org.alfresco.rest.rm.community.base.DataProviderClass; | ||||
| import org.alfresco.rest.rm.community.model.CapabilityModel; | ||||
| import org.alfresco.rest.rm.community.model.fileplan.FilePlan; | ||||
| import org.alfresco.rest.rm.community.model.fileplan.FilePlanProperties; | ||||
| import org.alfresco.rest.rm.community.model.hold.Hold; | ||||
| @@ -76,6 +85,9 @@ import org.alfresco.rest.rm.community.model.hold.HoldCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection; | ||||
| import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryProperties; | ||||
| import org.alfresco.rest.rm.community.model.role.Role; | ||||
| import org.alfresco.rest.rm.community.model.role.RoleCollection; | ||||
| import org.alfresco.rest.rm.community.model.user.UserCapabilities; | ||||
| import org.alfresco.rest.rm.community.requests.gscore.api.RMSiteAPI; | ||||
| import org.alfresco.utility.constants.ContainerName; | ||||
| import org.alfresco.utility.model.UserModel; | ||||
| @@ -87,6 +99,7 @@ import org.alfresco.utility.report.Bug; | ||||
|  * @author Rodica Sutu | ||||
|  * @since 2.6 | ||||
|  */ | ||||
| @SuppressWarnings("PMD.UnitTestShouldIncludeAssert") | ||||
| public class FilePlanTests extends BaseRMRestTest | ||||
| { | ||||
|     // ** Number of children (for children creation test) */ | ||||
| @@ -266,7 +279,7 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|      * When I ask the API to create a root record category | ||||
|      * Then it is created as a root record category | ||||
|      * </pre> | ||||
|      *  | ||||
|      * | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When I use the API to create a folder (cm:folder type) into the fileplan | ||||
| @@ -314,7 +327,7 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|      * When I ask the API to create a root category having the same name | ||||
|      * Then  the response code received is 409 - name clashes with an existing node | ||||
|      * </pre> | ||||
|      *  | ||||
|      * | ||||
|      * <pre> | ||||
|      * Given a root category | ||||
|      * When I ask the API to create a root category having the same name  with autoRename parameter on true | ||||
| @@ -594,4 +607,171 @@ public class FilePlanTests extends BaseRMRestTest | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When rmAdmin user ask the API for roles | ||||
|      * It provides list of all default roles | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void listFilePlanAllDefaultRoles() | ||||
|     { | ||||
|         List<String> defaultRolesDisplayNames = asList(IN_PLACE_READERS.displayName, ROLE_RM_ADMIN.displayName, ROLE_RM_MANAGER.displayName, ROLE_RM_POWER_USER.displayName, ROLE_RM_USER.displayName, IN_PLACE_WRITERS.displayName, ROLE_RM_SECURITY_OFFICER.displayName); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS); | ||||
|         assertStatusCode(OK); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertTrue(defaultRolesDisplayNames.contains(role.getDisplayLabel())); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When rmAdmin user ask the API for roles with SystemRoles as false | ||||
|      * It provides list of all roles excluding SystemRoles | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void listFilePlanAllRolesExcludeSystemRoles() | ||||
|     { | ||||
|         String parameters = "where=(systemRoles=false)"; | ||||
|         List<String> systemRolesDisplayNames = asList(IN_PLACE_WRITERS.displayName, IN_PLACE_READERS.displayName); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertFalse(systemRolesDisplayNames.contains(role.getDisplayLabel())); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a non-RM user asks the API for the roles | ||||
|      * Then the status code 403 (Permission denied) is return | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void nonRmUserFilePlanRoles() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel nonRMuser = getDataUser().createRandomTestUser("testUser"); | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         getRestAPIFactory().getFilePlansAPI(nonRMuser).getFilePlanRoles(FILE_PLAN_ALIAS); | ||||
|         assertStatusCode(FORBIDDEN); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a RM_Manager user asks the API for the roles | ||||
|      * returns the RM_Manager role and capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void rmManagerFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel managerUser = getDataUser().createRandomTestUser("managerUser"); | ||||
|         // Assign RecordsManager role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(managerUser.getUsername(), ROLE_RM_MANAGER.roleId); | ||||
|         String parameters = "where=(personId='" + managerUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(managerUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertEquals(ROLE_RM_MANAGER.displayName, role.getDisplayLabel()); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a User with more than one role asks the API for the roles and relation | ||||
|      * returns the roles and capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void multipleRoleUserFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         // Create a random user | ||||
|         UserModel rmUser = getDataUser().createRandomTestUser("rmUser"); | ||||
|         // Assign rmUser role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmUser.getUsername(), ROLE_RM_USER.roleId); | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmUser.getUsername(), ROLE_RM_POWER_USER.roleId); | ||||
|         String parameters = "where=(personId='" + rmUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(rmUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 2); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertTrue(role.getDisplayLabel().equals(ROLE_RM_USER.displayName) || role.getDisplayLabel().equals(ROLE_RM_POWER_USER.displayName)); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When a new user with a new role asks the API for the roles and relation | ||||
|      * returns the new role and new capabilities | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void newRoleUserFilePlanRolesAndCapabilities() | ||||
|     { | ||||
|         /** A list of capabilities. */ | ||||
|         Set<String> newCapabilities = newHashSet(UserCapabilities.VIEW_RECORDS_CAP, UserCapabilities.DECLARE_RECORDS_CAP); | ||||
|         // Create a new role using old API | ||||
|         getRmRolesAndActionsV0API().createRole(getAdminUser().getUsername(), getAdminUser().getPassword(), "NewTestRole", | ||||
|                 "New Role Label", newCapabilities); | ||||
|         // Create a random user | ||||
|         UserModel rmNewUser = getDataUser().createRandomTestUser("rmPowerUser"); | ||||
|         // Assign New role to user | ||||
|         getRestAPIFactory().getRMUserAPI().assignRoleToUser(rmNewUser.getUsername(), "NewTestRole"); | ||||
|         String parameters = "where=(personId='" + rmNewUser.getUsername() + "')"; | ||||
|         // Call to new API to get the roles and capabilities | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI(rmNewUser).getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 1); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             List<CapabilityModel> capabilities = roleModelEntry.getEntry().getCapabilities(); | ||||
|             capabilities.forEach(capabilityModel -> { | ||||
|                 assertTrue(newCapabilities.contains(capabilityModel.name())); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * <pre> | ||||
|      * Given that a file plan exists | ||||
|      * When API call happens with Capability filter | ||||
|      * returns roles associated with the capability | ||||
|      * </pre> | ||||
|      */ | ||||
|     @Test | ||||
|     public void filePlanRolesAndCapabilitiesFilter() | ||||
|     { | ||||
|         String parameters = "where=(systemRoles=true and capabilityName in ('ManageRules'))"; | ||||
|         // Call to new API to get the roles and capabilities, filter by capability, include assigned users | ||||
|         RoleCollection roleCollection = getRestAPIFactory().getFilePlansAPI().getFilePlanRoles(FILE_PLAN_ALIAS, parameters); | ||||
|         assertStatusCode(OK); | ||||
|         assertEquals(roleCollection.getEntries().size(), 1); | ||||
|         roleCollection.getEntries().forEach(roleModelEntry -> { | ||||
|             Role role = roleModelEntry.getEntry(); | ||||
|             assertEquals(ROLE_RM_ADMIN.displayName, role.getDisplayLabel()); | ||||
|             assertNotNull(role.getCapabilities()); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -134,6 +134,16 @@ public class AddToHoldsBulkV1Tests extends BaseRMRestTest | ||||
|                 .until(() -> getRestAPIFactory().getSearchAPI(null).search(searchRequest).getPagination() | ||||
|                         .getTotalItems() == NUMBER_OF_FILES); | ||||
|  | ||||
|         RestRequestQueryModel ancestorReq = getContentFromFolderAndAllSubfoldersQuery(rootFolder.getNodeRefWithoutVersion()); | ||||
|         SearchRequest ancestorSearchRequest = new SearchRequest(); | ||||
|         ancestorSearchRequest.setQuery(ancestorReq); | ||||
|  | ||||
|         STEP("Wait until paths are indexed."); | ||||
|         // to improve stability on CI - seems that sometimes during big load we need to wait longer for the condition | ||||
|         await().atMost(120, TimeUnit.SECONDS) | ||||
|                 .until(() -> getRestAPIFactory().getSearchAPI(null).search(ancestorSearchRequest).getPagination() | ||||
|                         .getTotalItems() == NUMBER_OF_FILES); | ||||
|  | ||||
|         holdBulkOperation = HoldBulkOperation.builder() | ||||
|                 .query(queryReq) | ||||
|                 .op(HoldBulkOperationType.ADD).build(); | ||||
|   | ||||
| @@ -37,7 +37,7 @@ import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPr | ||||
|  | ||||
| import java.util.Collections; | ||||
|  | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.json.JSONObject; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.testng.annotations.Test; | ||||
| @@ -56,7 +56,7 @@ import org.alfresco.test.AlfrescoTest; | ||||
|  | ||||
| /** | ||||
|  * Add Relationship tests | ||||
|  *  | ||||
|  * | ||||
|  * @author Kavit Shah | ||||
|  */ | ||||
| public class AddRelationshipTests extends BaseRMRestTest | ||||
|   | ||||
| @@ -45,7 +45,7 @@ import java.time.Instant; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.commons.lang.StringUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.apache.http.HttpEntity; | ||||
| import org.apache.http.HttpResponse; | ||||
| import org.apache.http.HttpStatus; | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -23,7 +23,7 @@ Recorded content can be explicitly destroyed whilst maintaining the original nod | ||||
| * License: Alfresco Community | ||||
| * Issue Tracker Link: [JIRA RM](https://issues.alfresco.com/jira/projects/RM/summary) | ||||
| * Contribution Model: Alfresco Closed Source | ||||
| * Documentation: [docs.alfresco.com (Records Management)](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services-Community-Edition/23.4/Alfresco-Governance-Services-Community-Edition/Introduction) | ||||
| * Documentation: [docs.alfresco.com (Records Management)](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1&component=Alfresco%20Governance%20Services%20Community%20Edition) | ||||
|  | ||||
| ***  | ||||
|  | ||||
|   | ||||
| @@ -21,18 +21,18 @@ RM is split into two main parts - a repository integration and a Share integrati | ||||
| * [Community License](../LICENSE.txt) | ||||
| * [Enterprise License](../../rm-enterprise/LICENSE.txt) (this file will only be present in clones of the Enterprise repository) | ||||
| * [Issue Tracker Link](https://issues.alfresco.com/jira/projects/RM) | ||||
| * [Community Documentation Link](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services-Community-Edition/23.4/Alfresco-Governance-Services-Community-Edition/Introduction) | ||||
| * [Enterprise Documentation Link](https://support.hyland.com/r/Alfresco/Alfresco-Governance-Services/23.4/Alfresco-Governance-Services/Introduction) | ||||
| * [Community Documentation Link](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1&component=Alfresco%20Governance%20Services%20Community%20Edition) | ||||
| * [Enterprise Documentation Link](https://support.hyland.com/access?dita:id=job1721300866386&vrm_version=25.1) | ||||
| * [Contribution Model](../../CONTRIBUTING.md) | ||||
|  | ||||
| ***  | ||||
|  | ||||
| ### Prerequisite Knowledge | ||||
| An understanding of Alfresco Content Services is assumed. The following pages from the [developer documentation](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services-Community-Edition/23.4/Alfresco-Content-Services-Community-Edition/Develop) give useful background information: | ||||
| An understanding of Alfresco Content Services is assumed. The following pages from the [developer documentation](https://support.hyland.com/access?dita:id=lsl1724405261585&vrm_version=25.2&component=Alfresco%20Content%20Services%20Community%20Edition) give useful background information: | ||||
|  | ||||
| * [ACS Architecture](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Software-Architecture) | ||||
| * [Platform Extensions](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Extension-Points-Overview) | ||||
| * [Share Extensions](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Share-UI-Extension-Points) | ||||
| * [ACS Architecture](https://support.hyland.com/access?dita:id=lfo1719554691023&vrm_version=25.2) | ||||
| * [Platform Extensions](https://support.hyland.com/access?dita:id=ifr1720080387005&vrm_version=25.2) | ||||
| * [Share Extensions](https://support.hyland.com/access?dita:id=wqu1720687386891&vrm_version=25.2) | ||||
|  | ||||
| ***  | ||||
|  | ||||
| @@ -44,12 +44,12 @@ The RM Share module communicates with the repository module via REST APIs. Inter | ||||
| * A DAO layer responsible for CRUD operations against the database. | ||||
|  | ||||
| #### REST API | ||||
| The REST API endpoints fall into two main types - v0 (Webscripts) and v1. The [v0 API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Web-Scripts) is older and not recommended for integrations. The [v1 API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/REST-API-Guide) is newer but isn't yet feature complete. If you are running RM locally then the GS API Explorer will be available at [this link](http://localhost:8080/gs-api-explorer/). | ||||
| The REST API endpoints fall into two main types - v0 (Webscripts) and v1. The [v0 API](https://support.hyland.com/access?dita:id=fga1720080409048&vrm_version=25.2) is older and not recommended for integrations. The [v1 API](https://support.hyland.com/access?dita:id=cmm1721136574006&vrm_version=25.2) is newer but isn't yet feature complete. If you are running RM locally then the GS API Explorer will be available at [this link](http://localhost:8080/gs-api-explorer/). | ||||
|  | ||||
| Internally the GS v1 REST API is built on the [Alfresco v1 REST API framework](https://community.alfresco.com/community/ecm/blog/2016/10/11/v1-rest-api-part-1-introduction). It aims to be consistent with this in terms of behaviour and naming. | ||||
|  | ||||
| #### Java Public API | ||||
| The Java service layer is fronted by a [Java Public API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Reference/Java-Foundation-API), which we will ensure backward compatible with previous releases. Before we remove any methods there will first be a release containing that method deprecated to allow third party integrations to migrate to a new method.  The Java Public API also includes a set of POJO objects which are needed to communicate with the services. It is easy to identify classes that are part of the Java Public API as they are annotated `@AlfrescoPublicApi`. | ||||
| The Java service layer is fronted by a [Java Public API](https://support.hyland.com/access?dita:id=lol1721390191517&vrm_version=25.2), which we will ensure backward compatible with previous releases. Before we remove any methods there will first be a release containing that method deprecated to allow third party integrations to migrate to a new method.  The Java Public API also includes a set of POJO objects which are needed to communicate with the services. It is easy to identify classes that are part of the Java Public API as they are annotated `@AlfrescoPublicApi`. | ||||
|  | ||||
| Each Java service will have at least four beans defined for it: | ||||
|  | ||||
| @@ -61,7 +61,7 @@ Each Java service will have at least four beans defined for it: | ||||
| #### DAOs | ||||
| The DAOs are not part of the Java Public API, but handle CRUD operations against RM stored data. We have some custom queries to improve performance for particularly heavy operations. | ||||
|  | ||||
| We use standard Alfresco [data modelling](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Content-Model-Extension-Point) to store RM metadata. We extend the [Alfresco patching mechanism](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/In-Process-Platform-Extension-Points/Patches) to provide community and enterprise schema upgrades. | ||||
| We use standard Alfresco [data modelling](https://support.hyland.com/access?dita:id=ekx1720080373621&vrm_version=25.2) to store RM metadata. We extend the [Alfresco patching mechanism](https://support.hyland.com/access?dita:id=ato1720080396825&vrm_version=25.2) to provide community and enterprise schema upgrades. | ||||
|  | ||||
| *** | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-parent</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <modules> | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| SOLR6_TAG=2.0.15 | ||||
| SOLR6_TAG=2.0.16 | ||||
| POSTGRES_TAG=16.6 | ||||
| ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8 | ||||
|   | ||||
| @@ -119,6 +119,11 @@ rm.patch.v35.holdNewChildAssocPatch.batchSize=1000 | ||||
| rm.haspermissionmap.read=Read | ||||
| rm.haspermissionmap.write=WriteProperties,AddChildren,ReadContent | ||||
|  | ||||
| # Extended Permissions | ||||
| # Enable matching the given username with the correct casing username when retrieving an IPR group. | ||||
| # Only needs to be used if there are owners that don't have the username in the correct casing. | ||||
| rm.extendedSecurity.enableUsernameNormalization=false | ||||
|  | ||||
| # | ||||
| # Extended auto-version behaviour.  If true and other auto-version properties are satisfied, then | ||||
| # a document will be auto-versioned when its type is changed. | ||||
|   | ||||
| @@ -33,5 +33,8 @@ | ||||
|  | ||||
|    <!-- content cleanser --> | ||||
|    <bean id="contentCleanser.522022M" class="org.alfresco.module.org_alfresco_module_rm.content.cleanser.ContentCleanser522022M"/> | ||||
|     | ||||
|     <!-- content cleanser --> | ||||
|    <bean id="contentCleanser.SevenPass" class="org.alfresco.module.org_alfresco_module_rm.content.cleanser.ContentCleanserSevenPass"/> | ||||
|  | ||||
| </beans> | ||||
|   | ||||
| @@ -15,6 +15,13 @@ | ||||
|       <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"/> | ||||
| @@ -55,18 +62,21 @@ | ||||
|  | ||||
|    <!-- Get list of node ids which reference given content url --> | ||||
|    <select id="select_NodeIdsWhichReferenceContentUrl" | ||||
|            parameterType="ContentUrl" | ||||
|            parameterMap="parameter_NodeIdsWhichReferenceContentUrl" | ||||
|            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) | ||||
|       WHERE | ||||
|          content_url_short = #{contentUrlShort} and | ||||
|          content_url_crc = #{contentUrlCrc} | ||||
|  | ||||
|          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 = ? | ||||
|    </select> | ||||
|  | ||||
|    <select id="select_RecordFoldersWithSchedules" | ||||
|   | ||||
| @@ -78,6 +78,12 @@ | ||||
|       <property name="transactionService" ref="transactionService" /> | ||||
|    </bean> | ||||
|  | ||||
|     <bean class="org.alfresco.rm.rest.api.fileplans.FilePlanRolesRelation"> | ||||
|         <property name="apiUtils" ref="apiUtils" /> | ||||
|         <property name="rmRoles" ref="rm.roles" /> | ||||
|         <property name="filePlanService" ref="FilePlanService" /> | ||||
|     </bean> | ||||
|  | ||||
|    <bean class="org.alfresco.rm.rest.api.holds.HoldsEntityResource" > | ||||
|       <property name="holdService" ref="HoldService" /> | ||||
|       <property name="apiUtils" ref="apiUtils" /> | ||||
| @@ -228,6 +234,11 @@ | ||||
|         <property name="siteSurfConfig" ref="rm.siteSurfConfig" /> | ||||
|    </bean> | ||||
|  | ||||
|     <bean id="rm.roles" class="org.alfresco.rm.rest.api.impl.RMRolesImpl"> | ||||
|         <property name="nodesModelFactory" ref="nodesModelFactory" /> | ||||
|         <property name="filePlanRoleService" ref="FilePlanRoleService"/> | ||||
|     </bean> | ||||
|  | ||||
|     <bean id="rm.siteSurfConfig" class="org.alfresco.rest.api.impl.SiteSurfConfig"> | ||||
|         <property name="configPath" value="alfresco/module/org_alfresco_module_rm/bootstrap/site"/> | ||||
|     </bean> | ||||
| @@ -280,4 +291,4 @@ | ||||
|       <property name="beanName" value="restJsonModule" /> | ||||
|       <property name="extendingBeanName" value="rm.restJsonModule" /> | ||||
|    </bean> | ||||
| </beans> | ||||
| </beans> | ||||
|   | ||||
| @@ -611,6 +611,7 @@ | ||||
|         <property name="authorityService" ref="authorityService"/> | ||||
|         <property name="permissionService" ref="permissionService"/> | ||||
|         <property name="transactionService" ref="transactionService"/> | ||||
|         <property name="enableUsernameNormalization" value="${rm.extendedSecurity.enableUsernameNormalization}" /> | ||||
|     </bean> | ||||
|  | ||||
|     <bean id="ExtendedSecurityService" class="org.springframework.aop.framework.ProxyFactoryBean"> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <properties> | ||||
| @@ -84,11 +84,6 @@ | ||||
|          <artifactId>junit</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.postgresql</groupId> | ||||
|          <artifactId>postgresql</artifactId> | ||||
|   | ||||
| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
|  | ||||
| package org.alfresco.module.org_alfresco_module_rm.content.cleanser; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
| /** | ||||
|  * DoD 5220-22M Seven Pass data cleansing implementation. | ||||
|  *  | ||||
|  */ | ||||
| public class ContentCleanserSevenPass extends ContentCleanser522022M | ||||
| { | ||||
|     /** | ||||
|      * @see org.alfresco.module.org_alfresco_module_rm.content.cleanser.ContentCleanser#cleanse(java.io.File) | ||||
|      */ | ||||
|     @Override | ||||
|     public void cleanse(File file) | ||||
|     { | ||||
|         super.cleanse(file); | ||||
|         overwrite(file, overwriteZeros); | ||||
|         overwrite(file, overwriteZeros); | ||||
|         overwrite(file, overwriteOnes); | ||||
|         overwrite(file, overwriteRandom); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -39,6 +39,7 @@ 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; | ||||
| @@ -191,13 +192,19 @@ 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, contentUrlEntity); | ||||
|         List<Long> nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, params); | ||||
|  | ||||
|         if (logger.isDebugEnabled()) | ||||
|         { | ||||
|   | ||||
| @@ -31,13 +31,16 @@ import static org.alfresco.service.cmr.security.PermissionService.GROUP_PREFIX; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import org.springframework.context.ApplicationListener; | ||||
| import org.springframework.context.event.ContextRefreshedEvent; | ||||
| import org.springframework.dao.ConcurrencyFailureException; | ||||
| import org.springframework.extensions.webscripts.ui.common.StringUtils; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.model.RenditionModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; | ||||
| @@ -96,6 +99,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|     /** transaction service */ | ||||
|     private TransactionService transactionService; | ||||
|  | ||||
|     private boolean enableUsernameNormalization; | ||||
|  | ||||
|     /** | ||||
|      * @param filePlanService | ||||
|      *            file plan service | ||||
| @@ -141,6 +146,15 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|         this.transactionService = transactionService; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param enableUsernameNormalization | ||||
|      *            enable username normalization to ensure correct casing | ||||
|      */ | ||||
|     public void setEnableUsernameNormalization(boolean enableUsernameNormalization) | ||||
|     { | ||||
|         this.enableUsernameNormalization = enableUsernameNormalization; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Application context refresh event handler | ||||
|      */ | ||||
| @@ -234,7 +248,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|      */ | ||||
|     private Set<String> getAuthorities(String group) | ||||
|     { | ||||
|         Set<String> result = new HashSet<>(); | ||||
|         Set<String> result = new LinkedHashSet<>(); | ||||
|         result.addAll(authorityService.getContainedAuthorities(null, group, true)); | ||||
|         return result; | ||||
|     } | ||||
| @@ -359,12 +373,18 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|     { | ||||
|         String group = null; | ||||
|  | ||||
|         // If enabled, the authorities are forced to match the correct casing of the usernames in case they were set | ||||
|         // with the incorrect casing. | ||||
|         // If not, it will just use the authorities as they are. | ||||
|         // In normal circumstances, the authorities are in the correct casing, so this is disabled by default. | ||||
|         Set<String> authoritySet = normalizeAuthorities(authorities); | ||||
|  | ||||
|         // find group or determine what the next index is if no group exists or there is a clash | ||||
|         Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authorities); | ||||
|         Pair<String, Integer> groupResult = findIPRGroup(groupPrefix, authoritySet); | ||||
|  | ||||
|         if (groupResult.getFirst() == null) | ||||
|         { | ||||
|             group = createIPRGroup(groupPrefix, authorities, groupResult.getSecond()); | ||||
|             group = createIPRGroup(groupPrefix, authoritySet, groupResult.getSecond()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @@ -399,7 +419,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|         while (hasMoreItems == true) | ||||
|         { | ||||
|             // get matching authorities | ||||
|             PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP, | ||||
|             PagingResults<String> results = authorityService.getAuthorities( | ||||
|                     AuthorityType.GROUP, | ||||
|                     RMAuthority.ZONE_APP_RM, | ||||
|                     groupShortNamePrefix, | ||||
|                     false, | ||||
| @@ -427,6 +448,63 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|         return new Pair<>(iprGroup, nextGroupIndex); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Given a set of authorities, normalizes the authority names to ensure correct casing. | ||||
|      *  | ||||
|      * @param authNames | ||||
|      * @return | ||||
|      */ | ||||
|     private Set<String> normalizeAuthorities(Set<String> authNames) | ||||
|     { | ||||
|         // If disabled or no authorities, return as is | ||||
|         if (!enableUsernameNormalization || authNames == null || authNames.isEmpty()) | ||||
|         { | ||||
|             return authNames; | ||||
|         } | ||||
|  | ||||
|         Set<String> normalizedAuthorities = new HashSet<>(); | ||||
|         for (String authorityName : authNames) | ||||
|         { | ||||
|             normalizedAuthorities.add(normalizeAuthorityName(authorityName)); | ||||
|         } | ||||
|         return normalizedAuthorities; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Usernames are case insensitive but affect the IPR group matching when set with different casing. For a given authority of type user, this method normalizes the authority name. If group, it returns the name as-is. | ||||
|      * | ||||
|      * @param authorityName | ||||
|      *            the authority name to normalize | ||||
|      * @return the normalized authority name | ||||
|      */ | ||||
|     private String normalizeAuthorityName(String authorityName) | ||||
|     { | ||||
|         if (authorityName == null || authorityName.startsWith(GROUP_PREFIX)) | ||||
|         { | ||||
|             return authorityName; | ||||
|         } | ||||
|  | ||||
|         // For users, attempt to get the correct casing from the username property of the user node | ||||
|         if (authorityService.authorityExists(authorityName)) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 NodeRef authorityNodeRef = authorityService.getAuthorityNodeRef(authorityName); | ||||
|                 if (authorityNodeRef != null) | ||||
|                 { | ||||
|                     String username = (String) nodeService.getProperty(authorityNodeRef, ContentModel.PROP_USERNAME); | ||||
|                     return username != null ? username : authorityName; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception e) | ||||
|             { | ||||
|                 // If anything goes wrong, fallback to the original name | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return authorityName; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Determines whether a group exactly matches a list of authorities. | ||||
|      * | ||||
| @@ -573,8 +651,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl | ||||
|         } | ||||
|         catch (DuplicateChildNodeNameException ex) | ||||
|         { | ||||
|             // the group was concurrently created | ||||
|             group = authorityService.getName(AuthorityType.GROUP, groupShortName); | ||||
|             // 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); | ||||
|         } | ||||
|  | ||||
|         return group; | ||||
|   | ||||
| @@ -33,6 +33,7 @@ import java.io.Serializable; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| @@ -325,8 +326,8 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme | ||||
|             return aclReaders; | ||||
|         } | ||||
|  | ||||
|         HashSet<String> assigned = new HashSet<>(); | ||||
|         HashSet<String> readers = new HashSet<>(); | ||||
|         Set<String> assigned = new LinkedHashSet<>(); | ||||
|         Set<String> readers = new LinkedHashSet<>(); | ||||
|  | ||||
|         for (AccessControlEntry ace : acl.getEntries()) | ||||
|         { | ||||
| @@ -412,8 +413,8 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme | ||||
|             return aclWriters; | ||||
|         } | ||||
|  | ||||
|         HashSet<String> assigned = new HashSet<>(); | ||||
|         HashSet<String> readers = new HashSet<>(); | ||||
|         Set<String> assigned = new LinkedHashSet<>(); | ||||
|         Set<String> readers = new LinkedHashSet<>(); | ||||
|  | ||||
|         for (AccessControlEntry ace : acl.getEntries()) | ||||
|         { | ||||
| @@ -485,7 +486,7 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme | ||||
|         Set<String> writers = getWriters(aclId); | ||||
|  | ||||
|         // add the current owner to the list of extended writers | ||||
|         Set<String> modifiedWrtiers = new HashSet<>(writers); | ||||
|         Set<String> modifiedWrtiers = new LinkedHashSet<>(writers); | ||||
|         String owner = ownableService.getOwner(nodeRef); | ||||
|         if (StringUtils.isNotBlank(owner) && | ||||
|                 !owner.equals(OwnableService.NO_OWNER) && | ||||
|   | ||||
| @@ -0,0 +1,56 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api; | ||||
|  | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| /** | ||||
|  * RM Roles API | ||||
|  */ | ||||
| public interface RMRoles | ||||
| { | ||||
|  | ||||
|     String PARAM_INCLUDE_ASSIGNED_USERS = "assignedUsers"; | ||||
|     String PARAM_INCLUDE_ASSIGNED_GROUPS = "assignedGroups"; | ||||
|     String PARAM_INCLUDE_SYSTEM_ROLES = "systemRoles"; | ||||
|     String PARAM_CAPABILITY_NAME = "capabilityName"; | ||||
|     String PARAM_PERSON_ID = "personId"; | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of roles. | ||||
|      * | ||||
|      * @param filePlan | ||||
|      *            the file plan node reference | ||||
|      * @param parameters | ||||
|      *            the {@link Parameters} object to get the parameters passed into the request including: - filter, sort & paging params (where, orderBy, skipCount, maxItems) - include param (personId, includeSystemRoles) | ||||
|      * @return a paged list of {@code org.alfresco.rm.rest.api.model.RoleModel} objects | ||||
|      */ | ||||
|     CollectionWithPagingInfo<RoleModel> getRoles(NodeRef filePlan, Parameters parameters); | ||||
| } | ||||
| @@ -0,0 +1,96 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.fileplans; | ||||
|  | ||||
| import static org.alfresco.util.ParameterCheck.mandatory; | ||||
|  | ||||
| import org.springframework.beans.factory.InitializingBean; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; | ||||
| import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; | ||||
| import org.alfresco.rest.framework.resource.RelationshipResource; | ||||
| import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.RMRoles; | ||||
| import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| @RelationshipResource(name = "roles", entityResource = FilePlanEntityResource.class, title = "Roles in a file plan") | ||||
| public class FilePlanRolesRelation implements RelationshipResourceAction.Read<RoleModel>, InitializingBean | ||||
| { | ||||
|     private RMRoles rmRoles; | ||||
|     private FilePlanService filePlanService; | ||||
|     private FilePlanComponentsApiUtils apiUtils; | ||||
|  | ||||
|     @Override | ||||
|     public void afterPropertiesSet() throws Exception | ||||
|     { | ||||
|         mandatory("rmRoles", this.rmRoles); | ||||
|         mandatory("apiUtils", this.apiUtils); | ||||
|         mandatory("filePlanService", this.filePlanService); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public CollectionWithPagingInfo<RoleModel> readAll(String filePlanId, Parameters params) | ||||
|     { | ||||
|         NodeRef filePlanNodeRef = getFilePlan(filePlanId); | ||||
|         if (filePlanNodeRef == null) | ||||
|         { | ||||
|             throw new EntityNotFoundException(filePlanId); | ||||
|         } | ||||
|  | ||||
|         return rmRoles.getRoles(filePlanNodeRef, params); | ||||
|     } | ||||
|  | ||||
|     private NodeRef getFilePlan(String filePlanId) | ||||
|     { | ||||
|         NodeRef filePlanNodeRef = apiUtils.lookupAndValidateNodeType(filePlanId, RecordsManagementModel.TYPE_FILE_PLAN); | ||||
|         if (!FilePlanComponentsApiUtils.FILE_PLAN_ALIAS.equals(filePlanId)) | ||||
|         { | ||||
|             filePlanNodeRef = filePlanService.getFilePlan(filePlanNodeRef); | ||||
|         } | ||||
|         return filePlanNodeRef; | ||||
|     } | ||||
|  | ||||
|     public void setRmRoles(RMRoles rmRoles) | ||||
|     { | ||||
|         this.rmRoles = rmRoles; | ||||
|     } | ||||
|  | ||||
|     public void setApiUtils(FilePlanComponentsApiUtils apiUtils) | ||||
|     { | ||||
|         this.apiUtils = apiUtils; | ||||
|     } | ||||
|  | ||||
|     public void setFilePlanService(FilePlanService filePlanService) | ||||
|     { | ||||
|         this.filePlanService = filePlanService; | ||||
|     } | ||||
| } | ||||
| @@ -30,6 +30,7 @@ package org.alfresco.rm.rest.api.impl; | ||||
| import java.io.Serializable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @@ -42,12 +43,15 @@ import org.slf4j.LoggerFactory; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Capability; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Group; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinitionImpl; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; | ||||
| import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent; | ||||
| import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.rest.api.Nodes; | ||||
| import org.alfresco.rest.api.model.AssocChild; | ||||
| import org.alfresco.rest.api.model.ContentInfo; | ||||
| @@ -55,7 +59,9 @@ import org.alfresco.rest.api.model.Node; | ||||
| import org.alfresco.rest.api.model.UserInfo; | ||||
| import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rm.rest.api.model.CapabilityModel; | ||||
| import org.alfresco.rm.rest.api.model.FilePlan; | ||||
| import org.alfresco.rm.rest.api.model.GroupModel; | ||||
| import org.alfresco.rm.rest.api.model.HoldModel; | ||||
| import org.alfresco.rm.rest.api.model.RMNode; | ||||
| import org.alfresco.rm.rest.api.model.Record; | ||||
| @@ -66,6 +72,7 @@ import org.alfresco.rm.rest.api.model.RetentionPeriod; | ||||
| import org.alfresco.rm.rest.api.model.RetentionSchedule; | ||||
| import org.alfresco.rm.rest.api.model.RetentionScheduleActionDefinition; | ||||
| import org.alfresco.rm.rest.api.model.RetentionSteps; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.rm.rest.api.model.Transfer; | ||||
| import org.alfresco.rm.rest.api.model.TransferChild; | ||||
| import org.alfresco.rm.rest.api.model.TransferContainer; | ||||
| @@ -696,6 +703,36 @@ public class ApiNodesModelFactory | ||||
|                 (String) info.getProperties().get(RecordsManagementModel.PROP_HOLD_REASON)); | ||||
|     } | ||||
|  | ||||
|     public RoleModel createRoleModel(Role role, List<String> assignedUsers, List<String> assignedGroups) | ||||
|     { | ||||
|         return new RoleModel(role.getName(), | ||||
|                 role.getDisplayLabel(), | ||||
|                 role.getCapabilities() | ||||
|                         .stream() | ||||
|                         .map(this::createCapabilityModel) | ||||
|                         .sorted(Comparator.comparing(CapabilityModel::name)) | ||||
|                         .toList(), | ||||
|                 role.getRoleGroupName(), | ||||
|                 role.getGroupShortName(), | ||||
|                 assignedUsers, | ||||
|                 assignedGroups); | ||||
|     } | ||||
|  | ||||
|     public CapabilityModel createCapabilityModel(Capability capability) | ||||
|     { | ||||
|         return new CapabilityModel(capability.getName(), capability.getTitle(), capability.getDescription(), | ||||
|                 createGroupModel(capability.getGroup()), capability.getIndex()); | ||||
|     } | ||||
|  | ||||
|     public GroupModel createGroupModel(Group group) | ||||
|     { | ||||
|         if (group == null) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|         return new GroupModel(group.getId(), group.getTitle()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates an object of type FilePlan | ||||
|      * | ||||
|   | ||||
| @@ -0,0 +1,264 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.impl; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Comparator; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.rest.antlr.WhereClauseParser; | ||||
| import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rest.framework.resource.parameters.where.Query; | ||||
| import org.alfresco.rest.framework.resource.parameters.where.QueryHelper; | ||||
| import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker; | ||||
| import org.alfresco.rm.rest.api.RMRoles; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
|  | ||||
| public class RMRolesImpl implements RMRoles | ||||
| { | ||||
|     private ApiNodesModelFactory nodesModelFactory; | ||||
|     private FilePlanRoleService filePlanRoleService; | ||||
|  | ||||
|     private static final Set<String> LIST_ROLES_QUERY_PROPERTIES = new HashSet<>(List.of(PARAM_PERSON_ID, PARAM_INCLUDE_SYSTEM_ROLES, PARAM_CAPABILITY_NAME)); | ||||
|  | ||||
|     @Override | ||||
|     public CollectionWithPagingInfo<RoleModel> getRoles(NodeRef filePlan, Parameters parameters) | ||||
|     { | ||||
|         var rolesFilter = getRolesFilter(parameters.getQuery()); | ||||
|         var roles = getRolesByFilter(filePlan, rolesFilter); | ||||
|  | ||||
|         var filteredRoles = roles.stream() | ||||
|                 .map(role -> createRoleModel(filePlan, role, parameters.getInclude())) | ||||
|                 .filter(hasRoleCapabilities(rolesFilter.getCapabilities())) | ||||
|                 .toList(); | ||||
|         var page = filteredRoles | ||||
|                 .stream() | ||||
|                 .sorted(Comparator.comparing(RoleModel::name)) | ||||
|                 .skip(parameters.getPaging().getSkipCount()) | ||||
|                 .limit(parameters.getPaging().getMaxItems()) | ||||
|                 .collect(Collectors.toCollection(LinkedList::new)); | ||||
|  | ||||
|         int totalItems = filteredRoles.size(); | ||||
|         boolean hasMore = parameters.getPaging().getSkipCount() + parameters.getPaging().getMaxItems() < totalItems; | ||||
|         return CollectionWithPagingInfo.asPaged(parameters.getPaging(), page, hasMore, totalItems); | ||||
|     } | ||||
|  | ||||
|     private Predicate<RoleModel> hasRoleCapabilities(List<String> capabilities) | ||||
|     { | ||||
|         return role -> capabilities == null || | ||||
|                 capabilities.isEmpty() || | ||||
|                 role.capabilities().stream().anyMatch(capability -> capabilities.contains(capability.name())); | ||||
|     } | ||||
|  | ||||
|     private Set<Role> getRolesByFilter(NodeRef filePlan, RolesFilter rolesFilter) | ||||
|     { | ||||
|         if (rolesFilter.getPersonId() != null) | ||||
|         { | ||||
|             return filePlanRoleService.getRolesByUser(filePlan, rolesFilter.getPersonId(), rolesFilter.includeSystemRoles()); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return filePlanRoleService.getRoles(filePlan, rolesFilter.includeSystemRoles()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private RoleModel createRoleModel(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         List<String> assignedUsers = getAssignedUsers(filePlan, role, include); | ||||
|         List<String> assignedGroups = getAssignedGroups(filePlan, role, include); | ||||
|  | ||||
|         return nodesModelFactory.createRoleModel(role, assignedUsers, assignedGroups); | ||||
|     } | ||||
|  | ||||
|     private List<String> getAssignedUsers(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         if (include != null && include.contains(PARAM_INCLUDE_ASSIGNED_USERS)) | ||||
|         { | ||||
|             return new ArrayList<>(filePlanRoleService.getAllAssignedToRole(filePlan, role.getName())); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private List<String> getAssignedGroups(NodeRef filePlan, Role role, List<String> include) | ||||
|     { | ||||
|         if (include != null && include.contains(PARAM_INCLUDE_ASSIGNED_GROUPS)) | ||||
|         { | ||||
|             return new ArrayList<>(filePlanRoleService.getGroupsAssignedToRole(filePlan, role.getName())); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory) | ||||
|     { | ||||
|         this.nodesModelFactory = nodesModelFactory; | ||||
|     } | ||||
|  | ||||
|     public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService) | ||||
|     { | ||||
|         this.filePlanRoleService = filePlanRoleService; | ||||
|     } | ||||
|  | ||||
|     private RolesFilter getRolesFilter(Query queryParameters) | ||||
|     { | ||||
|         var rolesFilterBuilder = RolesFilter.builder(); | ||||
|  | ||||
|         if (queryParameters != null) | ||||
|         { | ||||
|             var propertyWalker = new RolesQueryWalker(); | ||||
|             QueryHelper.walk(queryParameters, propertyWalker); | ||||
|  | ||||
|             rolesFilterBuilder | ||||
|                     .withPersonId(propertyWalker.getPersonId()) | ||||
|                     .withCapabilities(propertyWalker.getCapabilitiesNames()) | ||||
|                     .withIncludeSystemRoles(propertyWalker.includeSystemRoles()); | ||||
|         } | ||||
|         return rolesFilterBuilder.build(); | ||||
|     } | ||||
|  | ||||
|     private static class RolesQueryWalker extends MapBasedQueryWalker | ||||
|     { | ||||
|         private List<String> capabilitiesNames; | ||||
|  | ||||
|         public RolesQueryWalker() | ||||
|         { | ||||
|             super(LIST_ROLES_QUERY_PROPERTIES, null); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void in(String propertyName, boolean negated, String... propertyValues) | ||||
|         { | ||||
|             if (negated) | ||||
|             { | ||||
|                 throw new InvalidArgumentException("Cannot use NOT for " + propertyName); | ||||
|             } | ||||
|  | ||||
|             if (PARAM_CAPABILITY_NAME.equalsIgnoreCase(propertyName)) | ||||
|             { | ||||
|                 capabilitiesNames = Arrays.asList(propertyValues); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void and() | ||||
|         { | ||||
|             // allow AND, e.g. personId='123' AND includeSystemRoles=true | ||||
|         } | ||||
|  | ||||
|         public List<String> getCapabilitiesNames() | ||||
|         { | ||||
|             return this.capabilitiesNames; | ||||
|         } | ||||
|  | ||||
|         public String getPersonId() | ||||
|         { | ||||
|             return getProperty(PARAM_PERSON_ID, WhereClauseParser.EQUALS, String.class); | ||||
|         } | ||||
|  | ||||
|         public Boolean includeSystemRoles() | ||||
|         { | ||||
|             return getProperty(PARAM_INCLUDE_SYSTEM_ROLES, WhereClauseParser.EQUALS, Boolean.class); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| class RolesFilter | ||||
| { | ||||
|     private String personId; | ||||
|     private boolean includeSystemRoles; | ||||
|     private List<String> capabilities; | ||||
|  | ||||
|     private RolesFilter() | ||||
|     {} | ||||
|  | ||||
|     public static RolesFilterBuilder builder() | ||||
|     { | ||||
|         return new RolesFilterBuilder(); | ||||
|     } | ||||
|  | ||||
|     public String getPersonId() | ||||
|     { | ||||
|         return personId; | ||||
|     } | ||||
|  | ||||
|     public boolean includeSystemRoles() | ||||
|     { | ||||
|         return includeSystemRoles; | ||||
|     } | ||||
|  | ||||
|     public List<String> getCapabilities() | ||||
|     { | ||||
|         return capabilities; | ||||
|     } | ||||
|  | ||||
|     public static class RolesFilterBuilder | ||||
|     { | ||||
|         private String personId; | ||||
|         private boolean includeSystemRoles = true; | ||||
|         private List<String> capabilities; | ||||
|  | ||||
|         public RolesFilterBuilder withPersonId(String personId) | ||||
|         { | ||||
|             this.personId = personId; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilterBuilder withIncludeSystemRoles(Boolean includeSystemRoles) | ||||
|         { | ||||
|             if (includeSystemRoles != null) | ||||
|             { | ||||
|                 this.includeSystemRoles = includeSystemRoles; | ||||
|             } | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilterBuilder withCapabilities(List<String> capabilities) | ||||
|         { | ||||
|             this.capabilities = capabilities; | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public RolesFilter build() | ||||
|         { | ||||
|             RolesFilter rolesFilter = new RolesFilter(); | ||||
|             rolesFilter.personId = this.personId; | ||||
|             rolesFilter.includeSystemRoles = this.includeSystemRoles; | ||||
|             rolesFilter.capabilities = this.capabilities; | ||||
|             return rolesFilter; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| public record CapabilityModel(String name, String title, String description, GroupModel group, int index) | ||||
| {} | ||||
| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| public record GroupModel(String id, String title) | ||||
| {} | ||||
| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public record RoleModel(String name, String displayLabel, List<CapabilityModel> capabilities, String roleGroupName, String groupShortName, List<String> assignedUsers, List<String> assignedGroups) | ||||
| {} | ||||
| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.model; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public record RoleModelList(List<RoleModel> roleModelList) | ||||
| {} | ||||
| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Package info that defines the Information Governance Roles REST API | ||||
|  * | ||||
|  * @author Damian Ujma | ||||
|  */ | ||||
| @WebApi(name = "gs", scope = Api.SCOPE.PUBLIC, version = 1) | ||||
| package org.alfresco.rm.rest.api.roles; | ||||
|  | ||||
| import org.alfresco.rest.framework.Api; | ||||
| import org.alfresco.rest.framework.WebApi; | ||||
| @@ -29,14 +29,23 @@ 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; | ||||
| @@ -206,7 +215,8 @@ 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; | ||||
|             } | ||||
| @@ -279,4 +289,238 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     public void testConcurrentSetWithRetry() | ||||
|     { | ||||
|         Set<String> extendedReaders = new HashSet<>(2); | ||||
|         Set<String> extendedWriters = new HashSet<>(2); | ||||
|  | ||||
|         Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters); | ||||
|  | ||||
|         // For each record created previously, spawn a thread to set extended security so we cause concurrency | ||||
|         // failure trying to create IPR groups with the same name | ||||
|         fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, true); | ||||
|  | ||||
|         // Look for duplicated IPR groups and verify all documents have the same groups assigned | ||||
|         verifyCreatedGroups(documents, false); | ||||
|  | ||||
|         AuthenticationUtil.clearCurrentSecurityContext(); | ||||
|     } | ||||
|  | ||||
|     public void testConcurrentSetWithoutRetry() | ||||
|     { | ||||
|         Set<String> extendedReaders = new HashSet<>(2); | ||||
|         Set<String> extendedWriters = new HashSet<>(2); | ||||
|  | ||||
|         Set<NodeRef> documents = setupConcurrentTestCase(10, extendedReaders, extendedWriters); | ||||
|  | ||||
|         // For each record created previously, spawn a thread to set extended security so we cause concurrency | ||||
|         // failure trying to create IPR groups with the same name. | ||||
|         // Since there is no retry, we expect to get a ConcurrencyFailureException | ||||
|         Assert.assertThrows(ConcurrencyFailureException.class, () -> { | ||||
|             fireParallelExecutionOfSetExtendedSecurity(documents, extendedReaders, extendedWriters, false); | ||||
|         }); | ||||
|  | ||||
|         // Look for duplicated IPR groups and verify all documents have the same groups assigned | ||||
|         // Since there was a ConcurrencyFailureException some threads failed to set extended security so some | ||||
|         // documents may not have IPR groups created. | ||||
|         verifyCreatedGroups(documents, true); | ||||
|  | ||||
|         AuthenticationUtil.clearCurrentSecurityContext(); | ||||
|     } | ||||
|  | ||||
|     private Set<NodeRef> setupConcurrentTestCase(int concurrentThreads, Set<String> extendedReaders, Set<String> extendedWriters) | ||||
|     { | ||||
|         final String usera = createTestUser(); | ||||
|         final String userb = createTestUser(); | ||||
|         final String owner = createTestUser(); | ||||
|  | ||||
|         extendedReaders.add(usera); | ||||
|         extendedReaders.add(userb); | ||||
|         extendedWriters.add(usera); | ||||
|         extendedWriters.add(userb); | ||||
|  | ||||
|         AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); | ||||
|  | ||||
|         // Create a site | ||||
|         NodeRef documentLib = createSite(new HashSet<>(), new HashSet<>()); | ||||
|  | ||||
|         // Create records in the site document library | ||||
|         return createRecords(concurrentThreads, documentLib, owner); | ||||
|     } | ||||
|  | ||||
|     private NodeRef createSite(Set<String> readers, Set<String> writers) | ||||
|     { | ||||
|         return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>() { | ||||
|             @Override | ||||
|             public NodeRef execute() throws Throwable | ||||
|             { | ||||
|                 final String siteShortName = GUID.generate(); | ||||
|                 siteService.createSite(null, siteShortName, "test", "test", SiteVisibility.PRIVATE); | ||||
|                 readers.forEach(reader -> siteService.setMembership(siteShortName, reader, SiteModel.SITE_CONSUMER)); | ||||
|                 writers.forEach(writer -> siteService.setMembership(siteShortName, writer, SiteModel.SITE_COLLABORATOR)); | ||||
|                 return siteService.createContainer(siteShortName, SiteService.DOCUMENT_LIBRARY, null, null); | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private Set<NodeRef> createRecords(int numRecords, NodeRef parent, String owner) | ||||
|     { | ||||
|         return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Set<NodeRef>>() { | ||||
|             @Override | ||||
|             public Set<NodeRef> execute() throws Throwable | ||||
|             { | ||||
|                 int createdRecords = 0; | ||||
|                 Set<NodeRef> documents = new HashSet<>(); | ||||
|                 while (createdRecords < numRecords) | ||||
|                 { | ||||
|                     final NodeRef doc = fileFolderService.create(parent, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef(); | ||||
|                     ownableService.setOwner(doc, owner); | ||||
|                     recordService.createRecord(filePlan, doc, rmFolder, true); | ||||
|                     recordService.file(doc); | ||||
|                     recordService.complete(doc); | ||||
|                     documents.add(doc); | ||||
|                     createdRecords++; | ||||
|                 } | ||||
|                 return documents; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers, boolean useRetry) | ||||
|     { | ||||
|         if (!useRetry) | ||||
|         { | ||||
|             setExtendedSecurity(doc, readers, writers); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() { | ||||
|             @Override | ||||
|             public Void execute() throws Throwable | ||||
|             { | ||||
|                 setExtendedSecurity(doc, readers, writers); | ||||
|                 return null; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private void setExtendedSecurity(NodeRef doc, Set<String> readers, Set<String> writers) | ||||
|     { | ||||
|         AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser(); | ||||
|         extendedSecurityService.set(doc, readers, writers); | ||||
|     } | ||||
|  | ||||
|     private void fireParallelExecutionOfSetExtendedSecurity(Set<NodeRef> documents, Set<String> extendedReaders, Set<String> extendedWriters, boolean useRetry) | ||||
|     { | ||||
|         CompletableFuture<?>[] futures = documents.stream() | ||||
|                 .map(doc -> CompletableFuture.runAsync(() -> setExtendedSecurity(doc, extendedReaders, extendedWriters, useRetry))) | ||||
|                 .toArray(CompletableFuture[]::new); | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             CompletableFuture.allOf(futures).join(); | ||||
|         } | ||||
|         catch (Exception e) | ||||
|         { | ||||
|             Throwable cause = e.getCause(); | ||||
|             if (cause instanceof ConcurrencyFailureException) | ||||
|             { | ||||
|                 throw (ConcurrencyFailureException) cause; | ||||
|             } | ||||
|             throw new RuntimeException("Error during parallel execution", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void verifyCreatedGroups(Set<NodeRef> documents, boolean onlyDuplicatesValidation) | ||||
|     { | ||||
|         retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() { | ||||
|             @Override | ||||
|             public Void execute() throws Throwable | ||||
|             { | ||||
|                 Set<String> expectedAuthorities = null; | ||||
|                 Set<Set<String>> errors = new HashSet<>(); | ||||
|                 for (NodeRef doc : documents) | ||||
|                 { | ||||
|                     Set<AccessPermission> permissions = permissionService.getAllSetPermissions(doc); | ||||
|                     Set<String> authorities = getDocumentAuthorities(permissions); | ||||
|                     Set<String> authoritiesById = getAuthorityIds(authorities); | ||||
|  | ||||
|                     verifyIPRGroups(authorities, onlyDuplicatesValidation); | ||||
|  | ||||
|                     if (onlyDuplicatesValidation) | ||||
|                     { | ||||
|                         // Some documents may not have IPR groups created if there was a ConcurrencyFailureException | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     // All documents should have the same exact set of groups assigned | ||||
|                     if (expectedAuthorities == null) | ||||
|                     { | ||||
|                         expectedAuthorities = authoritiesById; | ||||
|                     } | ||||
|  | ||||
|                     if (!expectedAuthorities.equals(authoritiesById)) | ||||
|                     { | ||||
|                         errors.add(authoritiesById); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 assertTrue("Unexpected authorities linked to document", errors.isEmpty()); | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         }, false, true); | ||||
|     } | ||||
|  | ||||
|     private Set<String> getDocumentAuthorities(Set<AccessPermission> permissions) | ||||
|     { | ||||
|         Set<String> authorities = new HashSet<>(); | ||||
|  | ||||
|         for (AccessPermission accessPermission : permissions) | ||||
|         { | ||||
|             String authority = accessPermission.getAuthority(); | ||||
|             String authName = authorityService.getName(AuthorityType.GROUP, authority); | ||||
|             authorities.add(authName); | ||||
|  | ||||
|         } | ||||
|         return authorities; | ||||
|     } | ||||
|  | ||||
|     private Set<String> getAuthorityIds(Set<String> authorities) | ||||
|     { | ||||
|         Set<String> authorityIds = new HashSet<>(); | ||||
|         for (String authority : authorities) | ||||
|         { | ||||
|             String authId = authorityService.getAuthorityNodeRef(authority) != null | ||||
|                     ? authorityService.getAuthorityNodeRef(authority).getId() | ||||
|                     : null; | ||||
|             authorityIds.add(authId); | ||||
|         } | ||||
|         return authorityIds; | ||||
|     } | ||||
|  | ||||
|     private void verifyIPRGroups(Set<String> authorities, boolean onlyDuplicatesValidation) | ||||
|     { | ||||
|         boolean hasGroupIPR = false; | ||||
|  | ||||
|         for (String authorityName : authorities) | ||||
|         { | ||||
|             String shortName = authorityService.getShortName(authorityName); | ||||
|  | ||||
|             if (authorityName.startsWith("GROUP_IPR")) | ||||
|             { | ||||
|                 hasGroupIPR = true; | ||||
|                 PagingResults<String> results = authorityService.getAuthorities(AuthorityType.GROUP, null, shortName, false, | ||||
|                         false, new PagingRequest(0, 10)); | ||||
|  | ||||
|                 assertEquals("No duplicated IPR group expected", 1, results.getPage().size()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (!onlyDuplicatesValidation) | ||||
|         { | ||||
|             assertTrue("No IPR Groups created", hasGroupIPR); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -4,7 +4,7 @@ | ||||
|  | ||||
| # Version label | ||||
| version.major=25 | ||||
| version.minor=2 | ||||
| version.minor=3 | ||||
| version.revision=0 | ||||
| version.label= | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,100 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.module.org_alfresco_module_rm.content.cleanser; | ||||
|  | ||||
| import static org.mockito.Mockito.times; | ||||
| import static org.mockito.Mockito.verify; | ||||
| import static org.mockito.Mockito.when; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
| import org.junit.Test; | ||||
| import org.mockito.InjectMocks; | ||||
| import org.mockito.Mock; | ||||
| import org.mockito.Spy; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; | ||||
| import org.alfresco.service.cmr.repository.ContentIOException; | ||||
|  | ||||
| /** | ||||
|  * Eager content store cleaner unit test. | ||||
|  *  | ||||
|  */ | ||||
| public class ContentCleanserSevenPassUnitTest extends BaseUnitTest | ||||
| { | ||||
|     @InjectMocks | ||||
|     @Spy | ||||
|     private ContentCleanserSevenPass contentCleanserSevenPass = new ContentCleanserSevenPass()  | ||||
|     { | ||||
|         /** dummy implementations */ | ||||
|         @Override | ||||
|         protected void overwrite(File file, OverwriteOperation overwriteOperation) | ||||
|         { | ||||
|             // Intentionally left empty | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     @Mock | ||||
|     private File mockedFile; | ||||
|  | ||||
|     /** | ||||
|      * Given that a file exists When I cleanse it Then the content is overwritten | ||||
|      */ | ||||
|     @Test | ||||
|     public void cleanseFile() | ||||
|     { | ||||
|         when(mockedFile.exists()).thenReturn(true); | ||||
|         when(mockedFile.canWrite()).thenReturn(true); | ||||
|         contentCleanserSevenPass.cleanse(mockedFile); | ||||
|         verify(contentCleanserSevenPass, times(2)).overwrite(mockedFile, contentCleanserSevenPass.overwriteOnes); | ||||
|         verify(contentCleanserSevenPass, times(3)).overwrite(mockedFile, contentCleanserSevenPass.overwriteZeros); | ||||
|         verify(contentCleanserSevenPass, times(2)).overwrite(mockedFile, contentCleanserSevenPass.overwriteRandom); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Given that the file does not exist When I cleanse it Then an exception is thrown | ||||
|      */ | ||||
|     @Test(expected = ContentIOException.class) | ||||
|     public void fileDoesNotExist() | ||||
|     { | ||||
|         when(mockedFile.exists()).thenReturn(false); | ||||
|         when(mockedFile.canWrite()).thenReturn(true); | ||||
|         contentCleanserSevenPass.cleanse(mockedFile); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Given that I can not write to the file When I cleanse it Then an exception is thrown | ||||
|      */ | ||||
|     @Test(expected = ContentIOException.class) | ||||
|     public void cantWriteToFile() | ||||
|     { | ||||
|         when(mockedFile.exists()).thenReturn(true); | ||||
|         when(mockedFile.canWrite()).thenReturn(false); | ||||
|         contentCleanserSevenPass.cleanse(mockedFile); | ||||
|     } | ||||
| } | ||||
| @@ -52,6 +52,7 @@ import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| import org.alfresco.model.ContentModel; | ||||
| import org.alfresco.model.RenditionModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; | ||||
| import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; | ||||
| @@ -67,6 +68,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti | ||||
| import org.alfresco.service.cmr.repository.ChildAssociationRef; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.alfresco.service.cmr.repository.NodeService; | ||||
| import org.alfresco.service.cmr.repository.StoreRef; | ||||
| import org.alfresco.service.cmr.security.AccessPermission; | ||||
| import org.alfresco.service.cmr.security.AccessStatus; | ||||
| import org.alfresco.service.cmr.security.AuthorityService; | ||||
| @@ -522,6 +524,104 @@ public class ExtendedSecurityServiceImplUnitTest | ||||
|         verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); | ||||
|          | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Given a node with no previous IPR groups assigned | ||||
|      * And having pre-existing IPR groups matching the ones we need | ||||
|      * When I add some read and write authorities but with a different casing | ||||
|      * Then the existing IPR groups are used | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     @Test public void addExtendedSecurityWithMixedCasingUsernames() | ||||
|     { | ||||
|         // Have the usernames in the node as the correct usernames but with incorrect casing | ||||
|         String user1 = "UseR"; | ||||
|         String user2 = "UseR_w"; | ||||
|  | ||||
|         // Incorrect IPR Group names | ||||
|         Set<String> diffCasingReaders = Stream.of(user1, GROUP).collect(Collectors.toSet()); | ||||
|         Set<String> diffCasingWriters = Stream.of(user2, GROUP_W).collect(Collectors.toSet()); | ||||
|         String wrongReadGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(READER_GROUP_PREFIX, diffCasingReaders); | ||||
|         String wrongWriteGroupPrefix = extendedSecurityService.getIPRGroupPrefixShortName(WRITER_GROUP_PREFIX, diffCasingWriters); | ||||
|         String wrongReadGroup = wrongReadGroupPrefix + "0"; | ||||
|         String wrongWriteGroup = wrongWriteGroupPrefix + "0"; | ||||
|  | ||||
|         // Correct Group names | ||||
|         String correctReadGroup = readGroupPrefix + "0"; | ||||
|         String correctWriteGroup = writeGroupPrefix + "0"; | ||||
|  | ||||
|         // If queried for the correct groups, return the results | ||||
|         PagingResults<String> mockedCorrectReadPResults = mock(PagingResults.class); | ||||
|         PagingResults<String> mockedCorrectWritePResults = mock(PagingResults.class); | ||||
|         when(mockedCorrectReadPResults.getPage()) | ||||
|             .thenReturn(Stream.of(GROUP_PREFIX + correctReadGroup).collect(Collectors.toList())); | ||||
|         when(mockedAuthorityService.getAuthorities( | ||||
|                 eq(AuthorityType.GROUP),  | ||||
|                 eq(RMAuthority.ZONE_APP_RM),  | ||||
|                 eq(readGroupPrefix), | ||||
|                 eq(false),  | ||||
|                 eq(false),  | ||||
|                 any(PagingRequest.class))) | ||||
|             .thenReturn(mockedCorrectReadPResults); | ||||
|          | ||||
|         when(mockedCorrectWritePResults.getPage()) | ||||
|             .thenReturn(Stream.of(GROUP_PREFIX + correctWriteGroup).collect(Collectors.toList())); | ||||
|         when(mockedAuthorityService.getAuthorities( | ||||
|                 eq(AuthorityType.GROUP),  | ||||
|                 eq(RMAuthority.ZONE_APP_RM),  | ||||
|                 eq(writeGroupPrefix), | ||||
|                 eq(false),  | ||||
|                 eq(false),  | ||||
|                 any(PagingRequest.class))) | ||||
|             .thenReturn(mockedCorrectWritePResults); | ||||
|  | ||||
|         // Don't return results for the incorrect groups (lenient as these may not be called with normalization enabled) | ||||
|         PagingResults<String> mockedWrongReadPResults = mock(PagingResults.class); | ||||
|         PagingResults<String> mockedWrongWritePResults = mock(PagingResults.class); | ||||
|         lenient().when(mockedWrongReadPResults.getPage()) | ||||
|             .thenReturn(Collections.emptyList()); | ||||
|         lenient().when(mockedAuthorityService.getAuthorities( | ||||
|                 eq(AuthorityType.GROUP),  | ||||
|                 eq(RMAuthority.ZONE_APP_RM),  | ||||
|                 eq(wrongReadGroupPrefix), | ||||
|                 eq(false),  | ||||
|                 eq(false),  | ||||
|                 any(PagingRequest.class))) | ||||
|             .thenReturn(mockedWrongReadPResults); | ||||
|          | ||||
|         lenient().when(mockedWrongWritePResults.getPage()) | ||||
|             .thenReturn(Collections.emptyList()); | ||||
|         lenient().when(mockedAuthorityService.getAuthorities( | ||||
|                 eq(AuthorityType.GROUP),  | ||||
|                 eq(RMAuthority.ZONE_APP_RM),  | ||||
|                 eq(wrongWriteGroupPrefix), | ||||
|                 eq(false),  | ||||
|                 eq(false),  | ||||
|                 any(PagingRequest.class))) | ||||
|             .thenReturn(mockedWrongWritePResults); | ||||
|  | ||||
|         // The users do exist, despite being in a different casing and are able to be retrieved | ||||
|         NodeRef noderefUser1 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, USER); | ||||
|         when(mockedAuthorityService.authorityExists(user1)).thenReturn(true); | ||||
|         when(mockedAuthorityService.getAuthorityNodeRef(user1)).thenReturn(noderefUser1); | ||||
|         when(mockedNodeService.getProperty(noderefUser1, ContentModel.PROP_USERNAME)).thenReturn(USER); | ||||
|  | ||||
|         NodeRef noderefUser2 = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, USER_W); | ||||
|         when(mockedAuthorityService.authorityExists(user2)).thenReturn(true); | ||||
|         when(mockedAuthorityService.getAuthorityNodeRef(user2)).thenReturn(noderefUser2); | ||||
|         when(mockedNodeService.getProperty(noderefUser2, ContentModel.PROP_USERNAME)).thenReturn(USER_W); | ||||
|  | ||||
|         // Set the extended security service to normalize usernames | ||||
|         extendedSecurityService.setEnableUsernameNormalization(true); | ||||
|         extendedSecurityService.set(nodeRef, diffCasingReaders, diffCasingWriters); | ||||
|  | ||||
|         // Verify that the incorrect read group is not created | ||||
|         verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, wrongReadGroup, wrongReadGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); | ||||
|  | ||||
|         // Verify that the incorrect write group is not created | ||||
|         verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, wrongWriteGroup, wrongWriteGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); | ||||
|  | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Given a node with no previous IPR groups assigned | ||||
| @@ -571,7 +671,7 @@ public class ExtendedSecurityServiceImplUnitTest | ||||
|             .thenReturn(Stream | ||||
|                 .of(USER_W, AlfMock.generateText()) | ||||
|                 .collect(Collectors.toSet())); | ||||
|          | ||||
|  | ||||
|         // add extended security | ||||
|         extendedSecurityService.set(nodeRef, READERS, WRITERS); | ||||
|          | ||||
| @@ -895,7 +995,7 @@ public class ExtendedSecurityServiceImplUnitTest | ||||
|         // group names | ||||
|         String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, 0); | ||||
|         String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, WRITERS, 0); | ||||
|          | ||||
|  | ||||
|         // setup renditions | ||||
|         NodeRef renditionNodeRef = AlfMock.generateNodeRef(mockedNodeService); | ||||
|         when(mockedNodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD)) | ||||
| @@ -904,7 +1004,7 @@ public class ExtendedSecurityServiceImplUnitTest | ||||
|             .thenReturn(renditionNodeRef); | ||||
|         when(mockedNodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL)) | ||||
|             .thenReturn(Collections.singletonList(mockedChildAssociationRef));         | ||||
|          | ||||
|  | ||||
|         // setup permissions | ||||
|         Set<AccessPermission> permissions = Stream | ||||
|             .of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0), | ||||
| @@ -913,17 +1013,17 @@ public class ExtendedSecurityServiceImplUnitTest | ||||
|             .collect(Collectors.toSet());         | ||||
|         when(mockedPermissionService.getAllSetPermissions(nodeRef)) | ||||
|             .thenReturn(permissions);       | ||||
|          | ||||
|  | ||||
|         // remove extended security | ||||
|         extendedSecurityService.remove(nodeRef); | ||||
|          | ||||
|  | ||||
|         // verify that the groups permissions have been removed | ||||
|         verify(mockedPermissionService).clearPermission(nodeRef, readGroup); | ||||
|         verify(mockedPermissionService).clearPermission(nodeRef, writeGroup); | ||||
|          | ||||
|  | ||||
|         // verify that the groups permissions have been removed from the rendition | ||||
|         verify(mockedPermissionService).clearPermission(renditionNodeRef, readGroup); | ||||
|         verify(mockedPermissionService).clearPermission(renditionNodeRef, writeGroup); | ||||
|          | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,177 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Records Management Module | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * - | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * - | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * - | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * - | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
| package org.alfresco.rm.rest.api.impl; | ||||
|  | ||||
| import org.alfresco.module.org_alfresco_module_rm.capability.Capability; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; | ||||
| import org.alfresco.module.org_alfresco_module_rm.role.Role; | ||||
| import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; | ||||
| import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; | ||||
| import org.alfresco.rest.framework.resource.parameters.Paging; | ||||
| import org.alfresco.rest.framework.resource.parameters.Parameters; | ||||
| import org.alfresco.rest.framework.tools.RecognizedParamsExtractor; | ||||
| import org.alfresco.rm.rest.api.model.CapabilityModel; | ||||
| import org.alfresco.rm.rest.api.model.RoleModel; | ||||
| import org.alfresco.service.cmr.repository.NodeRef; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
|  | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.mockito.Mockito.*; | ||||
|  | ||||
| public class RMRolesImplUnitTest extends BaseUnitTest { | ||||
|  | ||||
|     private final RecognizedParamsExtractor queryExtractor = new RecognizedParamsExtractor() {}; | ||||
|  | ||||
|     private RMRolesImpl rmRolesImpl; | ||||
|     private FilePlanRoleService mockedFilePlanRoleService; | ||||
|     private ApiNodesModelFactory mockedNodesModelFactory; | ||||
|  | ||||
|     private final Capability viewRecordsCapability = mock(Capability.class); | ||||
|     private final Capability editMetadataCapability = mock(Capability.class); | ||||
|  | ||||
|     private final Role role1 = new Role("Role1", "Role 1", Set.of(viewRecordsCapability), "Group1"); | ||||
|     private final Role role2 = new Role("Role2", "Role 2", Set.of(editMetadataCapability), "Group2"); | ||||
|  | ||||
|     private final RoleModel roleModel1 = new RoleModel("Role1", "Role 1", List.of(new CapabilityModel("ViewRecords", "", "", null, 0)), "Group1", null, List.of("User1"), List.of("Group1")); | ||||
|     private final RoleModel roleModel2 = new RoleModel("Role2", "Role 2", List.of(new CapabilityModel("EditMetadata", "", "", null, 0)), "Group2", null, List.of("User2"), List.of("Group2")); | ||||
|  | ||||
|     private final NodeRef filePlan = new NodeRef("workspace://SpacesStore/testFilePlan"); | ||||
|  | ||||
|     private final Parameters parameters = mock(Parameters.class); | ||||
|     private final Paging paging = mock(Paging.class); | ||||
|  | ||||
|     @Before | ||||
|     public void setUp() { | ||||
|         mockedFilePlanRoleService = mock(FilePlanRoleService.class); | ||||
|         mockedNodesModelFactory = mock(ApiNodesModelFactory.class); | ||||
|  | ||||
|         rmRolesImpl = new RMRolesImpl(); | ||||
|         rmRolesImpl.setFilePlanRoleService(mockedFilePlanRoleService); | ||||
|         rmRolesImpl.setNodesModelFactory(mockedNodesModelFactory); | ||||
|  | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, true)).thenReturn(Set.of(role1, role2)); | ||||
|         when(mockedNodesModelFactory.createRoleModel(eq(role1), any(), any())).thenReturn(roleModel1); | ||||
|         when(mockedNodesModelFactory.createRoleModel(eq(role2), any(), any())).thenReturn(roleModel2); | ||||
|  | ||||
|         when(viewRecordsCapability.getName()).thenReturn("ViewRecords"); | ||||
|         when(editMetadataCapability.getName()).thenReturn("EditMetadata"); | ||||
|  | ||||
|         when(parameters.getPaging()).thenReturn(paging); | ||||
|         when(paging.getSkipCount()).thenReturn(0); | ||||
|         when(paging.getMaxItems()).thenReturn(10); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_NoFilters() { | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         List<RoleModel> roleModelList = (List<RoleModel>) result.getCollection(); | ||||
|         assertEquals(2, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1, roleModel2), roleModelList); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role2), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_WithPersonId() { | ||||
|         // given | ||||
|         String personId = "testUser"; | ||||
|         when(mockedFilePlanRoleService.getRolesByUser(filePlan, personId, true)).thenReturn(Set.of(role1)); | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(personId='" + personId + "')")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRolesByUser(filePlan, personId, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetNonSystemRoles() { | ||||
|         //given | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, false)).thenReturn(Set.of(role2)); | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(systemRoles=false)")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel2), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, false); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role2), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_WithCapabilitiesFilter() { | ||||
|         // given | ||||
|         when(parameters.getQuery()).thenReturn(queryExtractor.getWhereClause("(capabilityName IN ('ViewRecords'))")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), result.getCollection()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(eq(role1), any(), any()); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testGetRoles_IncludeAssignedUsersAndGroups() { | ||||
|         // given | ||||
|         when(mockedFilePlanRoleService.getRoles(filePlan, true)).thenReturn(Set.of(role1)); | ||||
|         when(mockedFilePlanRoleService.getAllAssignedToRole(filePlan, "Role1")).thenReturn(Set.of("User1")); | ||||
|         when(mockedFilePlanRoleService.getGroupsAssignedToRole(filePlan, "Role1")).thenReturn(Set.of("Group1")); | ||||
|  | ||||
|         when(parameters.getInclude()).thenReturn(List.of("assignedUsers", "assignedGroups")); | ||||
|  | ||||
|         // when | ||||
|         CollectionWithPagingInfo<RoleModel> result = rmRolesImpl.getRoles(filePlan, parameters); | ||||
|  | ||||
|         // then | ||||
|         List<RoleModel> roleModelList = (List<RoleModel>) result.getCollection(); | ||||
|         assertEquals(1, (int) result.getTotalItems()); | ||||
|         assertEquals(List.of(roleModel1), roleModelList); | ||||
|         assertEquals(List.of("User1"), roleModelList.get(0).assignedUsers()); | ||||
|         assertEquals(List.of("Group1"), roleModelList.get(0).assignedGroups()); | ||||
|         verify(mockedFilePlanRoleService).getRoles(filePlan, true); | ||||
|         verify(mockedFilePlanRoleService).getAllAssignedToRole(filePlan, "Role1"); | ||||
|         verify(mockedFilePlanRoleService).getGroupsAssignedToRole(filePlan, "Role1"); | ||||
|         verify(mockedNodesModelFactory).createRoleModel(role1, List.of("User1"), List.of("Group1")); | ||||
|     } | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-governance-services-community-repo-parent</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -540,6 +540,66 @@ paths: | ||||
|           description: Unexpected error | ||||
|           schema: | ||||
|             $ref: '#/definitions/Error' | ||||
|   '/file-plans/{filePlanId}/roles': | ||||
|     get: | ||||
|       tags: | ||||
|         - file-plans | ||||
|       summary: Get roles in a file plan | ||||
|       description: | | ||||
|         Gets a list of roles for the specified file plan **filePlanId**. | ||||
|          | ||||
|         You can use the **include** parameter to return additional information. | ||||
|          | ||||
|         The **where** parameter can also be used to filter by **personId**, **systemRoles** and **capabilityName**. | ||||
|  | ||||
|         You can use the **where** parameter to  | ||||
|         * filter roles by user: | ||||
|         `where=(personId='admin')` | ||||
|          | ||||
|         * not include system roles in the results: | ||||
|         `where=(systemRoles=false)` | ||||
|          | ||||
|         * filter roles by specified capabilities: | ||||
|         `where=(capabilityName in ('AddToHold', 'ViewRecords'))` | ||||
|          | ||||
|         This may be combined with all filter, as shown below: | ||||
|          | ||||
|         `where=(systemRoles=false and personId='johndoe' and capabilityName in ('AddToHold', 'ViewRecords'))` | ||||
|  | ||||
|       operationId: getFilePlanRoles | ||||
|       parameters: | ||||
|         - $ref: '#/parameters/filePlanIdWithAliasParam' | ||||
|         - $ref: '#/parameters/whereParam' | ||||
|         - $ref: '#/parameters/rolesIncludeParam' | ||||
|         - $ref: '#/parameters/skipCountParam' | ||||
|         - $ref: '#/parameters/maxItemsParam' | ||||
|       produces: | ||||
|         - application/json | ||||
|       responses: | ||||
|         '200': | ||||
|           description: Successful response | ||||
|           schema: | ||||
|             type: object | ||||
|             properties: | ||||
|               list: | ||||
|                 type: array | ||||
|                 items: | ||||
|                   $ref: '#/definitions/RoleModel' | ||||
|               pagination: | ||||
|                 $ref: '#/definitions/Pagination' | ||||
|         '400': | ||||
|           description: | | ||||
|             Invalid parameter: value of **maxItems** or **skipCount**, or **include**, or **where** is invalid | ||||
|         '401': | ||||
|           description: Authentication failed | ||||
|         '403': | ||||
|           description: Current user does not have permission to read **filePlanId** | ||||
|         '404': | ||||
|           description: "**filePlanId** does not exist" | ||||
|         default: | ||||
|           description: Unexpected error | ||||
|           schema: | ||||
|             $ref: '#/definitions/Error' | ||||
|   ## Unfiled records containers | ||||
|   '/unfiled-containers/{unfiledContainerId}': | ||||
|     get: | ||||
| @@ -3307,6 +3367,21 @@ parameters: | ||||
|       * actions | ||||
|     required: false | ||||
|     type: string | ||||
|   rolesIncludeParam: | ||||
|     name: include | ||||
|     in: query | ||||
|     description: | | ||||
|       Returns additional information about roles. Any optional field from the response model can be requested. For example: | ||||
|       * assignedUsers | ||||
|       * assignedGroups | ||||
|     required: false | ||||
|     type: string | ||||
|   whereParam: | ||||
|     name: where | ||||
|     in: query | ||||
|     description: A string to restrict the returned objects by using a predicate. | ||||
|     required: false | ||||
|     type: string | ||||
| definitions: | ||||
|   FilePlanComponentBodyUpdate: | ||||
|     type: object | ||||
| @@ -4389,6 +4464,49 @@ definitions: | ||||
|       query: | ||||
|         description: The query which may have been generated in some way from the userQuery | ||||
|         type: string | ||||
|   CapabilityModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       name: | ||||
|         type: string | ||||
|       title: | ||||
|         type: string | ||||
|       description: | ||||
|         type: string | ||||
|       group: | ||||
|         $ref: '#/definitions/GroupModel' | ||||
|       index: | ||||
|         type: integer | ||||
|   GroupModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       id: | ||||
|         type: string | ||||
|       title: | ||||
|         type: string | ||||
|   RoleModel: | ||||
|     type: object | ||||
|     properties: | ||||
|       name: | ||||
|         type: string | ||||
|       displayLabel: | ||||
|         type: string | ||||
|       capabilities: | ||||
|         type: array | ||||
|         items: | ||||
|           $ref: '#/definitions/CapabilityModel' | ||||
|       roleGroupName: | ||||
|         type: string | ||||
|       groupShortName: | ||||
|         type: string | ||||
|       assignedUsers: | ||||
|         type: array | ||||
|         items: | ||||
|           type: string | ||||
|       assignedGroups: | ||||
|         type: array | ||||
|         items: | ||||
|           type: string | ||||
|   HoldBulkOperation: | ||||
|     type: object | ||||
|     properties: | ||||
| @@ -4929,4 +5047,4 @@ definitions: | ||||
|           - SiteConsumer | ||||
|           - SiteCollaborator | ||||
|           - SiteContributor | ||||
|           - SiteManager | ||||
|           - SiteManager | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-amps</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -51,8 +51,8 @@ | ||||
|             </exclusions> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>commons-lang</groupId> | ||||
|             <artifactId>commons-lang</artifactId> | ||||
|             <groupId>org.apache.commons</groupId> | ||||
|             <artifactId>commons-lang3</artifactId> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|  | ||||
| @@ -70,11 +70,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.postgresql</groupId> | ||||
|             <artifactId>postgresql</artifactId> | ||||
|   | ||||
| @@ -28,7 +28,7 @@ import java.util.ResourceBundle; | ||||
| import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| import org.apache.commons.lang.StringEscapeUtils; | ||||
| import org.apache.commons.lang3.StringEscapeUtils; | ||||
| import org.json.simple.JSONObject; | ||||
| import org.springframework.extensions.webscripts.Cache; | ||||
| import org.springframework.extensions.webscripts.Status; | ||||
| @@ -92,7 +92,7 @@ public class WikiPageGet extends AbstractWikiWebScript | ||||
|                 { | ||||
|                     links.add(link); | ||||
|                     // build the list of available pages | ||||
|                     WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml(link)); | ||||
|                     WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml4(link)); | ||||
|                     if (wikiPage != null) | ||||
|                     { | ||||
|                         pageTitles.add(wikiPage.getTitle()); | ||||
|   | ||||
| @@ -91,6 +91,15 @@ function doclist_getAllNodes(parsedArgs, filterParams, query, totalItemCount) | ||||
|    }; | ||||
| } | ||||
|  | ||||
| function sanitizeJunkFavouriteKeys(favourites){ | ||||
|    for (var key in favourites) { | ||||
|       if (!key || key.trim() === "") { | ||||
|          delete favourites[key]; | ||||
|       } | ||||
|    } | ||||
|    return favourites; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Main entry point: Create collection of documents and folders in the given space | ||||
|  * | ||||
| @@ -123,6 +132,47 @@ function doclist_main() | ||||
|     | ||||
|    if (logger.isLoggingEnabled()) | ||||
|       logger.log("doclist.lib.js - NodeRef: " + parsedArgs.nodeRef + " Query: " + query); | ||||
|  | ||||
|    favourites = sanitizeJunkFavouriteKeys(favourites); | ||||
|    if(query === null) | ||||
|    { | ||||
|       return { | ||||
|          luceneQuery: "", | ||||
|          paging: { | ||||
|             totalRecords: 0, | ||||
|             startIndex: 0 | ||||
|          }, | ||||
|          container: parsedArgs.rootNode, | ||||
|          parent: null, | ||||
|          onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"), | ||||
|          itemCount: { | ||||
|             folders: 0, | ||||
|             documents: 0 | ||||
|          }, | ||||
|          items: [], | ||||
|          customJSON: slingshotDocLib.getJSON() | ||||
|       }; | ||||
|    } | ||||
|  | ||||
|    if(Object.keys(favourites).length === 0 && query === null) | ||||
|    { | ||||
|       return { | ||||
|          luceneQuery: "", | ||||
|          paging: { | ||||
|             totalRecords: 0, | ||||
|             startIndex: 0 | ||||
|          }, | ||||
|          container: parsedArgs.rootNode, | ||||
|          parent: null, | ||||
|          onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"), | ||||
|          itemCount: { | ||||
|             folders: 0, | ||||
|             documents: 0 | ||||
|          }, | ||||
|          items: [], | ||||
|          customJSON: slingshotDocLib.getJSON() | ||||
|       }; | ||||
|    } | ||||
|     | ||||
|    var totalItemCount = filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : -1; | ||||
|    // For all sites documentLibrary query we pull in all available results and post filter | ||||
|   | ||||
| @@ -182,11 +182,14 @@ var Filters = | ||||
|          case "favourites": | ||||
|             for (var favourite in favourites) | ||||
|             { | ||||
|                if (filterQuery) | ||||
|                if (favourite && favourite.trim() !== "") | ||||
|                { | ||||
|                   filterQuery += " OR "; | ||||
|                   if (filterQuery) | ||||
|                   { | ||||
|                      filterQuery += " OR "; | ||||
|                   } | ||||
|                   filterQuery += "ID:\"" + favourite + "\""; | ||||
|                } | ||||
|                filterQuery += "ID:\"" + favourite + "\""; | ||||
|             } | ||||
|              | ||||
|             if (filterQuery.length !== 0) | ||||
| @@ -201,7 +204,13 @@ var Filters = | ||||
|             else | ||||
|             { | ||||
|                // empty favourites query | ||||
|                filterQuery = "+ID:\"\""; | ||||
|                logger.warn("No favourites found for user: " + person.properties.userName); | ||||
|                return { | ||||
|                   query: null, | ||||
|                   limitResults: 0, | ||||
|                   sort: [], | ||||
|                   language: "lucene" | ||||
|                }; | ||||
|             } | ||||
|              | ||||
|             filterParams.query = filterQuery; | ||||
| @@ -224,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 + " +PATH:\"/cm:taggable/cm:" + search.ISO9075Encode(filterData) + "/member\""; | ||||
|             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 "category": | ||||
|             // Remove any trailing "/" character | ||||
| @@ -240,8 +249,15 @@ var Filters = | ||||
|             { | ||||
|                filterData = filterData.slice(0, -1); | ||||
|             } | ||||
|             filterQuery = this.constructPathQuery(parsedArgs); | ||||
|             filterParams.query = filterQuery + " +PATH:\"/cm:categoryRoot/cm:generalclassifiable" + Filters.iso9075EncodePath(filterData) + "/member\""; | ||||
|  | ||||
|             var categoryNodeRef = this.getCategoryNodeRef(filterData); | ||||
|  | ||||
|             if (categoryNodeRef && search.findNode(categoryNodeRef) != null) { | ||||
|                filterParams.query = filterQuery + ' +@cm\\:categories:"' + categoryNodeRef + '"'; | ||||
|             } else { | ||||
|                logger.warn("category filter: skipping invalid category node : " + categoryNodeRef); | ||||
|             } | ||||
|             filterParams.language = "fts-alfresco"; | ||||
|             break; | ||||
|  | ||||
|          case "aspect": | ||||
| @@ -262,11 +278,24 @@ var Filters = | ||||
|       { | ||||
|          filterParams.query += " " + (Filters.TYPE_MAP[parsedArgs.type] || ""); | ||||
|       } | ||||
|  | ||||
|       logger.warn("Final Query : " + filterParams.query); | ||||
|       return filterParams; | ||||
|    }, | ||||
|     | ||||
|    constructPathQuery: function constructPathQuery(parsedArgs) | ||||
|  | ||||
|     getCategoryNodeRef: function(categoryName) { | ||||
|         var results = search.luceneSearch( | ||||
|             'PATH:"/cm:categoryRoot/cm:generalclassifiable//*" AND @cm\\:name:"' + categoryName + '"' | ||||
|         ); | ||||
|  | ||||
|         if (results && results.length > 0) { | ||||
|             return results[0].nodeRef.toString(); | ||||
|         } | ||||
|  | ||||
|         logger.warn("Category not found: " + categoryName); | ||||
|         return null; | ||||
|     }, | ||||
|  | ||||
|    constructPathQuery: function(parsedArgs) | ||||
|    { | ||||
|       var pathQuery = ""; | ||||
|       if (parsedArgs.libraryRoot != companyhome || parsedArgs.nodeRef != "alfresco://company/home") | ||||
|   | ||||
| @@ -80,6 +80,11 @@ function runAction(p_params) | ||||
|          { | ||||
|             result.fileExist = true; | ||||
|          } | ||||
|          if (error.indexOf("FolderExistsException") != -1) | ||||
|          { | ||||
|             result.fileExist = true; | ||||
|             result.type = "folder"; | ||||
|          } | ||||
|       } | ||||
|        | ||||
|       results.push(result); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import java.util.regex.Matcher; | ||||
| import java.util.regex.Pattern; | ||||
| import jakarta.transaction.UserTransaction; | ||||
|  | ||||
| import org.apache.commons.lang.StringEscapeUtils; | ||||
| import org.apache.commons.lang3.StringEscapeUtils; | ||||
| import org.apache.commons.logging.Log; | ||||
| import org.apache.commons.logging.LogFactory; | ||||
| import org.json.JSONArray; | ||||
| @@ -958,7 +958,7 @@ public class WikiRestApiTest extends BaseWebScriptTest | ||||
|                 String link = m.group(1); | ||||
|                 link += "?title=<script>alert('xss');</script>"; | ||||
|                 WikiPageInfo wikiPage2 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, link); | ||||
|                 WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml(link)); | ||||
|                 WikiPageInfo wikiPage1 = this.wikiService.getWikiPage(SITE_SHORT_NAME_WIKI, StringEscapeUtils.unescapeHtml4(link)); | ||||
|                 assertEquals(wikiPage2, wikiPage1); | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|    <parent> | ||||
|       <groupId>org.alfresco</groupId> | ||||
|       <artifactId>alfresco-community-repo</artifactId> | ||||
|       <version>25.2.0.13</version> | ||||
|       <version>25.3.0.63</version> | ||||
|    </parent> | ||||
|  | ||||
|    <dependencies> | ||||
| @@ -126,11 +126,6 @@ | ||||
|          <artifactId>junit</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>com.epam.reportportal</groupId> | ||||
|          <artifactId>agent-java-testng</artifactId> | ||||
|          <scope>test</scope> | ||||
|       </dependency> | ||||
|       <dependency> | ||||
|          <groupId>org.mockito</groupId> | ||||
|          <artifactId>mockito-core</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -144,7 +144,7 @@ | ||||
|         <dependency> | ||||
|             <groupId>com.fasterxml.woodstox</groupId> | ||||
|             <artifactId>woodstox-core</artifactId> | ||||
|             <version>7.0.0</version> | ||||
|             <version>7.1.1</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- the cxf libs were updated, see dependencyManagement section --> | ||||
| @@ -247,11 +247,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.antlr</groupId> | ||||
|             <artifactId>gunit</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -46,11 +46,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-core</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,6 +9,6 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
| </project> | ||||
|   | ||||
| @@ -1,141 +0,0 @@ | ||||
| Instructions for Generating Repository SSL Keystores | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| <store password> is the keystore password. The file ${dir.keystore}/ssl-keystore-passwords.properties contains passwords for the SSL keystore, | ||||
| ${dir.keystore}/ssl-truststore-passwords.properties contains passwords for the SSL truststore. | ||||
|  | ||||
| These instructions will create an RSA public/private key pair for the repository with a certificate that has been signed by the Alfresco Certificate Authority (CA). | ||||
| It will also create a truststore for the repository containing the CA certificate; this will be used to authenticate connections to specific repository | ||||
| URLs from Solr. It assumes the existence of the Alfresco CA key and certificate to sign the repository certificate; for security reasons these are not generally available. | ||||
| You can either generate your own CA key and certificate (see instructions below) or use a recognised Certificate Authority such as Verisign. For Alfresco employees the key | ||||
| and certificate are available in svn. | ||||
|  | ||||
| (i) Generate the repository public/private key pair in a keystore: | ||||
|  | ||||
| $ keytool -genkey -alias ssl.repo -keyalg RSA -keystore ssl.keystore -storetype JCEKS -storepass <store password> | ||||
| Enter keystore password:   | ||||
| Re-enter new password:  | ||||
| What is your first and last name? | ||||
|   [Unknown]:  Alfresco Repository | ||||
| What is the name of your organizational unit? | ||||
|   [Unknown]:   | ||||
| What is the name of your organization? | ||||
|   [Unknown]:  Alfresco Software Ltd. | ||||
| What is the name of your City or Locality? | ||||
|   [Unknown]:  Maidenhead  | ||||
| What is the name of your State or Province? | ||||
|   [Unknown]:  UK | ||||
| What is the two-letter country code for this unit? | ||||
|   [Unknown]:  GB | ||||
| Is CN=Alfresco Repository, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB correct? | ||||
|   [no]:  yes | ||||
|  | ||||
| Enter key password for <ssl.repo> | ||||
| 	(RETURN if same as keystore password):   | ||||
| 	 | ||||
| (ii) Generate a certificate request for the repository key | ||||
|  | ||||
| $ keytool -keystore ssl.keystore -alias ssl.repo -certreq -file repo.csr -storetype JCEKS -storepass <store password> | ||||
|  | ||||
| (iii) Alfresco CA signs the certificate request, creating a certificate that is valid for 365 days. | ||||
|  | ||||
| $ openssl x509 -CA ca.crt -CAkey ca.key -CAcreateserial -req -in repo.csr -out repo.crt -days 365 | ||||
| Signature ok | ||||
| subject=/C=GB/ST=UK/L=Maidenhead/O=Alfresco Software Ltd./OU=Unknown/CN=Alfresco Repository | ||||
| Getting CA Private Key | ||||
| Enter pass phrase for ca.key: | ||||
|  | ||||
| (iv) Import the Alfresco CA key into the repository key store | ||||
|  | ||||
| $ keytool -import -alias ssl.alfreco.ca -file ca.crt -keystore ssl.keystore -storetype JCEKS -storepass <store password> | ||||
| Enter keystore password:   | ||||
| Owner: CN=Alfresco CA, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB | ||||
| Issuer: CN=Alfresco CA, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB | ||||
| Serial number: 805ba6dc8f62f8b8 | ||||
| Valid from: Fri Aug 12 13:28:58 BST 2011 until: Mon Aug 09 13:28:58 BST 2021 | ||||
| Certificate fingerprints: | ||||
| 	 MD5:  4B:45:94:2D:8E:98:E8:12:04:67:AD:AE:48:3C:F5:A0 | ||||
| 	 SHA1: 74:42:22:D0:52:AD:82:7A:FD:37:46:37:91:91:F4:77:89:3A:C9:A3 | ||||
| 	 Signature algorithm name: SHA1withRSA | ||||
| 	 Version: 3 | ||||
|  | ||||
| Extensions:  | ||||
|  | ||||
| #1: ObjectId: 2.5.29.14 Criticality=false | ||||
| SubjectKeyIdentifier [ | ||||
| KeyIdentifier [ | ||||
| 0000: 08 42 40 DC FE 4A 50 87   05 2B 38 4D 92 70 8E 51  .B@..JP..+8M.p.Q | ||||
| 0010: 4E 38 71 D6                                        N8q. | ||||
| ] | ||||
| ] | ||||
|  | ||||
| #2: ObjectId: 2.5.29.19 Criticality=false | ||||
| BasicConstraints:[ | ||||
|   CA:true | ||||
|   PathLen:2147483647 | ||||
| ] | ||||
|  | ||||
| #3: ObjectId: 2.5.29.35 Criticality=false | ||||
| AuthorityKeyIdentifier [ | ||||
| KeyIdentifier [ | ||||
| 0000: 08 42 40 DC FE 4A 50 87   05 2B 38 4D 92 70 8E 51  .B@..JP..+8M.p.Q | ||||
| 0010: 4E 38 71 D6                                        N8q. | ||||
| ] | ||||
|  | ||||
| [CN=Alfresco CA, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB] | ||||
| SerialNumber: [    805ba6dc 8f62f8b8] | ||||
| ] | ||||
|  | ||||
| Trust this certificate? [no]:  yes | ||||
| Certificate was added to keystore | ||||
|  | ||||
| (v) Import the CA-signed repository certificate into the repository keystore | ||||
|  | ||||
| $ keytool -import -alias ssl.repo -file repo.crt -keystore ssl.keystore -storetype JCEKS -storepass <store password> | ||||
| Enter keystore password:   | ||||
| Certificate reply was installed in keystore | ||||
|  | ||||
| (vi) Convert the repository keystore to a pkcs12 keystore (for use in browsers such as Firefox). Give the pkcs12 key store the key store password 'alfresco'. | ||||
|  | ||||
| keytool -importkeystore -srckeystore ssl.keystore -srcstorepass <keystore password> -srcstoretype JCEKS -srcalias ssl.repo -srckeypass kT9X6oe68t -destkeystore firefox.p12 -deststoretype pkcs12 -deststorepass alfresco -destalias ssl.repo -destkeypass alfresco | ||||
|  | ||||
| (vi) Create a repository truststore containing the Alfresco CA certificate | ||||
|  | ||||
| keytool -import -alias ssl.alfreco.ca -file ca.crt -keystore ssl.keystore -storetype JCEKS -storepass <store password> | ||||
| keytool -import -alias alfreco.ca -file ca.crt -keystore ssl.truststore -storetype JCEKS -storepass <store password> | ||||
|  | ||||
| (vii) Copy the keystore and truststore to the repository keystore location defined by the property 'dir.keystore'. | ||||
| (viii) Update the SSL properties i.e. properties starting with the prefixes 'alfresco.encryption.ssl.keystore' and 'alfresco.encryption.ssl.truststore'. | ||||
|  | ||||
| Instructions for Generating a Certificate Authority (CA) Key and Certificate | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| (i) Generate the CA private key | ||||
|  | ||||
| $ openssl genrsa -des3 -out ca.key 1024 | ||||
| Generating RSA private key, 1024 bit long modulus | ||||
| ..........++++++ | ||||
| ..++++++ | ||||
| e is 65537 (0x10001) | ||||
| Enter pass phrase for ca.key: | ||||
| Verifying - Enter pass phrase for ca.key: | ||||
|  | ||||
| (ii) Generate the CA self-signed certificate | ||||
|  | ||||
| $ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt | ||||
| Enter pass phrase for ca.key: | ||||
| You are about to be asked to enter information that will be incorporated | ||||
| into your certificate request. | ||||
| What you are about to enter is what is called a Distinguished Name or a DN. | ||||
| There are quite a few fields but you can leave some blank | ||||
| For some fields there will be a default value, | ||||
| If you enter '.', the field will be left blank. | ||||
| ----- | ||||
| Country Name (2 letter code) [AU]:GB | ||||
| State or Province Name (full name) [Some-State]:UK | ||||
| Locality Name (eg, city) []:Maidenhead | ||||
| Organization Name (eg, company) [Internet Widgits Pty Ltd]:Alfresco Software Ltd. | ||||
| Organizational Unit Name (eg, section) []: | ||||
| Common Name (eg, YOUR name) []:Alfresco CA | ||||
| Email Address []: | ||||
|  | ||||
| @@ -1,58 +0,0 @@ | ||||
| @rem Please edit the variables below to suit your installation | ||||
| @rem Note: for an installation created by the Alfresco installer, you only need to edit ALFRESCO_HOME | ||||
|  | ||||
| @rem Alfresco installation directory | ||||
| set ALFRESCO_HOME=C:\Alfresco-5.2 | ||||
| @rem The directory containing the alfresco keystores, as referenced by keystoreFile and truststoreFile attributes in tomcat\conf\server.xml | ||||
| set ALFRESCO_KEYSTORE_HOME=%ALFRESCO_HOME%\alf_data\keystore | ||||
| @rem Java installation directory | ||||
| set JAVA_HOME=%ALFRESCO_HOME%\java | ||||
| @rem Location in which new keystore files will be generated | ||||
| set CERTIFICATE_HOME=%USERPROFILE% | ||||
| @rem The repository server certificate subject name, as specified in tomcat\conf\tomcat-users.xml with roles="repository" | ||||
| set REPO_CERT_DNAME=CN=Alfresco Repository, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB | ||||
| @rem The SOLR client certificate subject name, as specified in tomcat\conf\tomcat-users.xml with roles="repoclient" | ||||
| set SOLR_CLIENT_CERT_DNAME=CN=Alfresco Repository Client, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB | ||||
| @rem The number of days before the certificate expires | ||||
| set CERTIFICATE_VALIDITY=36525 | ||||
|  | ||||
| @rem Ensure certificate output dir exists | ||||
| @if not exist "%CERTIFICATE_HOME%" mkdir "%CERTIFICATE_HOME%" | ||||
|  | ||||
| @rem Remove old output files (note they are backed up elsewhere) | ||||
| @if exist "%CERTIFICATE_HOME%\ssl.keystore" del "%CERTIFICATE_HOME%\ssl.keystore" | ||||
| @if exist "%CERTIFICATE_HOME%\ssl.truststore" del "%CERTIFICATE_HOME%\ssl.truststore" | ||||
| @if exist "%CERTIFICATE_HOME%\browser.p12" del "%CERTIFICATE_HOME%\browser.p12" | ||||
| @if exist "%CERTIFICATE_HOME%\ssl.repo.client.keystore" del "%CERTIFICATE_HOME%\ssl.repo.client.keystore" | ||||
| @if exist "%CERTIFICATE_HOME%\ssl.repo.client.truststore" del "%CERTIFICATE_HOME%\ssl.repo.client.truststore" | ||||
|  | ||||
| @rem Generate new self-signed certificates for the repository and solr | ||||
| "%JAVA_HOME%\bin\keytool" -genkeypair -keyalg RSA -dname "%REPO_CERT_DNAME%" -validity %CERTIFICATE_VALIDITY% -alias ssl.repo -keypass kT9X6oe68t -keystore "%CERTIFICATE_HOME%\ssl.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "%JAVA_HOME%\bin\keytool" -exportcert -alias ssl.repo -file "%CERTIFICATE_HOME%\ssl.repo.crt" -keystore "%CERTIFICATE_HOME%\ssl.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "%JAVA_HOME%\bin\keytool" -genkeypair -keyalg RSA -dname "%SOLR_CLIENT_CERT_DNAME%" -validity %CERTIFICATE_VALIDITY% -alias ssl.repo.client -keypass kT9X6oe68t -keystore "%CERTIFICATE_HOME%\ssl.repo.client.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "%JAVA_HOME%\bin\keytool" -exportcert -alias ssl.repo.client -file "%CERTIFICATE_HOME%\ssl.repo.client.crt" -keystore "%CERTIFICATE_HOME%\ssl.repo.client.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
|  | ||||
| @rem Create trust relationship between repository and solr | ||||
| "%JAVA_HOME%\bin\keytool" -importcert -noprompt -alias ssl.repo.client -file "%CERTIFICATE_HOME%\ssl.repo.client.crt" -keystore "%CERTIFICATE_HOME%\ssl.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| @rem Create trust relationship between repository and itself - used for searches | ||||
| "%JAVA_HOME%\bin\keytool" -importcert -noprompt -alias ssl.repo -file "%CERTIFICATE_HOME%\ssl.repo.crt" -keystore "%CERTIFICATE_HOME%\ssl.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| @rem Create trust relationship between solr and repository | ||||
| "%JAVA_HOME%\bin\keytool" -importcert -noprompt -alias ssl.repo -file "%CERTIFICATE_HOME%\ssl.repo.crt" -keystore "%CERTIFICATE_HOME%\ssl.repo.client.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| @rem Export repository keystore to pkcs12 format for browser compatibility | ||||
| "%JAVA_HOME%\bin\keytool" -importkeystore -srckeystore "%CERTIFICATE_HOME%\ssl.keystore" -srcstorepass kT9X6oe68t -srcstoretype JCEKS -srcalias ssl.repo -srckeypass kT9X6oe68t -destkeystore "%CERTIFICATE_HOME%\browser.p12" -deststoretype pkcs12 -deststorepass alfresco -destalias ssl.repo -destkeypass alfresco | ||||
|  | ||||
| @rem Ensure keystore dir actually exists | ||||
| @if not exist "%ALFRESCO_KEYSTORE_HOME%" mkdir "%ALFRESCO_KEYSTORE_HOME%" | ||||
|  | ||||
| @rem Install the new files | ||||
| copy /Y "%CERTIFICATE_HOME%\ssl.keystore" "%ALFRESCO_KEYSTORE_HOME%\ssl.keystore" | ||||
| copy /Y "%CERTIFICATE_HOME%\ssl.truststore" "%ALFRESCO_KEYSTORE_HOME%\ssl.truststore" | ||||
| copy /Y "%CERTIFICATE_HOME%\browser.p12" "%ALFRESCO_KEYSTORE_HOME%\browser.p12" | ||||
|  | ||||
| @echo **************************************** | ||||
| @echo You must copy the following files to the correct location. | ||||
| @echo %CERTIFICATE_HOME%\ssl.repo.client.keystore | ||||
| @echo %CERTIFICATE_HOME%\ssl.repo.client.truststore | ||||
| @echo eg. for Solr 4 the location is SOLR_HOME\workspace-SpacesStore\conf and SOLR_HOME\archive-SpacesStore\conf   | ||||
| @echo Please ensure that you set dir.keystore=%ALFRESCO_KEYSTORE_HOME% in alfresco-global.properties | ||||
| @echo **************************************** | ||||
| @@ -1,82 +0,0 @@ | ||||
| #! /bin/sh | ||||
| # Please edit the variables below to suit your installation | ||||
| # Note: for an installation created by the Alfresco installer, you only need to edit ALFRESCO_HOME | ||||
|  | ||||
| # Alfresco installation directory | ||||
| if [ -z "$ALFRESCO_HOME" ]; then | ||||
|     ALFRESCO_HOME=/opt/alfresco-5.2 | ||||
|     echo "Setting ALFRESCO_HOME to $ALFRESCO_HOME" | ||||
| fi | ||||
|  | ||||
| # The directory containing the alfresco keystores, as referenced by keystoreFile and truststoreFile attributes in tomcat/conf/server.xml | ||||
| ALFRESCO_KEYSTORE_HOME=$ALFRESCO_HOME/alf_data/keystore | ||||
|  | ||||
| # Location in which new keystore files will be generated | ||||
| if [ -z "$CERTIFICATE_HOME" ]; then | ||||
|     CERTIFICATE_HOME=$HOME | ||||
|     echo "Certificates will be generated in $CERTIFICATE_HOME and then moved to $ALFRESCO_KEYSTORE_HOME" | ||||
| fi | ||||
|  | ||||
| # Java installation directory | ||||
| JAVA_HOME=$ALFRESCO_HOME/java | ||||
|  | ||||
| # The repository server certificate subject name, as specified in tomcat/conf/tomcat-users.xml with roles="repository" | ||||
| REPO_CERT_DNAME="CN=Alfresco Repository, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB" | ||||
| # The SOLR client certificate subject name, as specified in tomcat/conf/tomcat-users.xml with roles="repoclient" | ||||
| SOLR_CLIENT_CERT_DNAME="CN=Alfresco Repository Client, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB" | ||||
| # The number of days before the certificate expires | ||||
| CERTIFICATE_VALIDITY=36525 | ||||
|  | ||||
| # Stop | ||||
| if [ -f "$ALFRESCO_HOME/alfresco.sh" ]; then "$ALFRESCO_HOME/alfresco.sh" stop; fi | ||||
|  | ||||
| # Ensure certificate output dir exists | ||||
| mkdir -p "$CERTIFICATE_HOME" | ||||
|  | ||||
| # Remove old output files (note they are backed up elsewhere) | ||||
| if [ -f "$CERTIFICATE_HOME/ssl.keystore" ]; then rm "$CERTIFICATE_HOME/ssl.keystore"; fi | ||||
| if [ -f "$CERTIFICATE_HOME/ssl.truststore" ]; then rm "$CERTIFICATE_HOME/ssl.truststore"; fi | ||||
| if [ -f "$CERTIFICATE_HOME/browser.p12" ]; then rm "$CERTIFICATE_HOME/browser.p12"; fi | ||||
| if [ -f "$CERTIFICATE_HOME/ssl.repo.client.keystore" ]; then rm "$CERTIFICATE_HOME/ssl.repo.client.keystore"; fi | ||||
| if [ -f "$CERTIFICATE_HOME/ssl.repo.client.truststore" ]; then rm "$CERTIFICATE_HOME/ssl.repo.client.truststore"; fi | ||||
|  | ||||
| # Generate new self-signed certificates for the repository and solr | ||||
| "$JAVA_HOME/bin/keytool" -genkeypair -keyalg RSA -dname "$REPO_CERT_DNAME" -validity $CERTIFICATE_VALIDITY -alias ssl.repo -keypass kT9X6oe68t -keystore "$CERTIFICATE_HOME/ssl.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "$JAVA_HOME/bin/keytool" -exportcert -alias ssl.repo -file "$CERTIFICATE_HOME/ssl.repo.crt" -keystore "$CERTIFICATE_HOME/ssl.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "$JAVA_HOME/bin/keytool" -genkeypair -keyalg RSA -dname "$SOLR_CLIENT_CERT_DNAME" -validity $CERTIFICATE_VALIDITY -alias ssl.repo.client -keypass kT9X6oe68t -keystore "$CERTIFICATE_HOME/ssl.repo.client.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| "$JAVA_HOME/bin/keytool" -exportcert -alias ssl.repo.client -file "$CERTIFICATE_HOME/ssl.repo.client.crt" -keystore "$CERTIFICATE_HOME/ssl.repo.client.keystore" -storetype JCEKS -storepass kT9X6oe68t | ||||
|  | ||||
| # Create trust relationship between repository and solr | ||||
| "$JAVA_HOME/bin/keytool" -importcert -noprompt -alias ssl.repo.client -file "$CERTIFICATE_HOME/ssl.repo.client.crt" -keystore "$CERTIFICATE_HOME/ssl.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| # Create trust relationship between repository and itself - used for searches | ||||
| "$JAVA_HOME/bin/keytool" -importcert -noprompt -alias ssl.repo -file "$CERTIFICATE_HOME/ssl.repo.crt" -keystore "$CERTIFICATE_HOME/ssl.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| # Create trust relationship between solr and repository | ||||
| "$JAVA_HOME/bin/keytool" -importcert -noprompt -alias ssl.repo -file "$CERTIFICATE_HOME/ssl.repo.crt" -keystore "$CERTIFICATE_HOME/ssl.repo.client.truststore" -storetype JCEKS -storepass kT9X6oe68t | ||||
| # Export repository keystore to pkcs12 format for browser compatibility | ||||
| "$JAVA_HOME/bin/keytool" -importkeystore -srckeystore "$CERTIFICATE_HOME/ssl.keystore" -srcstorepass kT9X6oe68t -srcstoretype JCEKS -srcalias ssl.repo -srckeypass kT9X6oe68t -destkeystore "$CERTIFICATE_HOME/browser.p12" -deststoretype pkcs12 -deststorepass alfresco -destalias ssl.repo -destkeypass alfresco | ||||
|  | ||||
| # Ensure keystore dir actually exists | ||||
| mkdir -p "$ALFRESCO_KEYSTORE_HOME" | ||||
|  | ||||
| # Back up old files | ||||
| cp "$ALFRESCO_KEYSTORE_HOME/ssl.keystore" "$ALFRESCO_KEYSTORE_HOME/ssl.keystore.old" | ||||
| cp "$ALFRESCO_KEYSTORE_HOME/ssl.truststore" "$ALFRESCO_KEYSTORE_HOME/ssl.truststore.old" | ||||
| cp "$ALFRESCO_KEYSTORE_HOME/browser.p12" "$ALFRESCO_KEYSTORE_HOME/browser.p12.old" | ||||
|  | ||||
| # Install the new files | ||||
| cp "$CERTIFICATE_HOME/ssl.keystore" "$ALFRESCO_KEYSTORE_HOME/ssl.keystore" | ||||
| cp "$CERTIFICATE_HOME/ssl.truststore" "$ALFRESCO_KEYSTORE_HOME/ssl.truststore" | ||||
| cp "$CERTIFICATE_HOME/browser.p12" "$ALFRESCO_KEYSTORE_HOME/browser.p12" | ||||
|  | ||||
| echo " " | ||||
| echo "*******************************************" | ||||
| echo "You must copy the following files to the correct location." | ||||
| echo " " | ||||
| echo " $CERTIFICATE_HOME/ssl.repo.client.keystore" | ||||
| echo " $CERTIFICATE_HOME/ssl.repo.client.truststore" | ||||
| echo " eg. for Solr 4 the location is SOLR_HOME/workspace-SpacesStore/conf/ and SOLR_HOME/archive-SpacesStore/conf/" | ||||
| echo " " | ||||
| echo "$ALFRESCO_KEYSTORE_HOME/browser.p12 has also been generated." | ||||
| echo " " | ||||
| echo "Please ensure that you set dir.keystore=$ALFRESCO_KEYSTORE_HOME in alfresco-global.properties" | ||||
| echo "*******************************************" | ||||
| @@ -37,8 +37,7 @@ commons-fileupload  http://jakarta.apache.org/commons/ | ||||
| commons-httpclient  http://jakarta.apache.org/commons/  | ||||
| commons-io  http://jakarta.apache.org/commons/  | ||||
| commons-jxpath  http://jakarta.apache.org/commons/  | ||||
| commons-lang    http://jakarta.apache.org/commons/  | ||||
| commons-lang3   http://jakarta.apache.org/commons/  | ||||
| commons-lang3   http://jakarta.apache.org/commons/ | ||||
| commons-logging http://jakarta.apache.org/commons/  | ||||
| commons-net http://jakarta.apache.org/commons/ | ||||
| commons-pool    http://jakarta.apache.org/commons/  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| # More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat | ||||
| FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:9622418e142fb4fe1c5320666ad61ea292bc5c98f3dd0b550b6add33d18f659f | ||||
|  | ||||
| FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:00d89fb84bda7bb37c17b0117adb2cfe4f7cbddcd6c1e42b0a67ea8dbb41a734 | ||||
| # 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.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| SOLR6_TAG=2.0.15 | ||||
| SOLR6_TAG=2.0.16 | ||||
| POSTGRES_TAG=16.6 | ||||
| ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8 | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <modules> | ||||
|   | ||||
| @@ -49,5 +49,6 @@ then | ||||
|   echo "Docker Compose started ok" | ||||
| else | ||||
|   echo "Docker Compose failed to start" >&2 | ||||
|   docker compose ${DOCKER_COMPOSES} logs --tail 200 | ||||
|   exit 1 | ||||
| fi | ||||
| fi | ||||
|   | ||||
| @@ -27,7 +27,7 @@ | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| **TAS**( **T**est **A**utomation **S**ystem)- **CMIS** is the project that handles the automated tests related only to CMIS API integrated with Alfresco One [Alfresco CMIS API](https://support.hyland.com/r/Alfresco/Alfresco-Content-Services/23.4/Alfresco-Content-Services/Develop/Reference/CMIS-API).  | ||||
| **TAS**( **T**est **A**utomation **S**ystem)- **CMIS** is the project that handles the automated tests related only to CMIS API integrated with Alfresco One [Alfresco CMIS API](https://support.hyland.com/access?dita:id=kvf1721390177551&vrm_version=25.2).  | ||||
|  | ||||
| It is based on Apache Maven, compatible with major IDEs and is using also Spring capabilities for dependency injection. | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <organization> | ||||
| @@ -68,16 +68,6 @@ | ||||
|                 </exclusion> | ||||
|             </exclusions> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import java.util.Date; | ||||
| import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; | ||||
| import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException; | ||||
| import org.apache.chemistry.opencmis.commons.exceptions.CmisUnauthorizedException; | ||||
| import org.apache.commons.lang.time.DateUtils; | ||||
| import org.apache.commons.lang3.time.DateUtils; | ||||
| import org.testng.annotations.BeforeClass; | ||||
| import org.testng.annotations.Test; | ||||
|  | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -36,11 +36,6 @@ | ||||
|             <artifactId>jakarta.mail-api</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -44,18 +44,6 @@ | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.sun.mail</groupId> | ||||
|             <artifactId>jakarta.mail</artifactId> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
| @@ -17,7 +17,7 @@ | ||||
|         <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.17.0</commons-lang3.version> | ||||
|         <commons-lang3.version>3.18.0</commons-lang3.version> | ||||
|         <scribejava-apis.version>8.3.3</scribejava-apis.version> | ||||
|         <java.version>17</java.version> | ||||
|     </properties> | ||||
| @@ -79,18 +79,6 @@ | ||||
|             <version>${commons-lang3.version}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>com.squareup.okhttp3</groupId> | ||||
|             <artifactId>okhttp</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>org.awaitility</groupId> | ||||
|             <artifactId>awaitility</artifactId> | ||||
| @@ -171,14 +159,14 @@ | ||||
|         <dependency> | ||||
|             <groupId>org.codehaus.groovy</groupId> | ||||
|             <artifactId>groovy</artifactId> | ||||
|             <version>3.0.23</version> | ||||
|             <version>3.0.25</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-json--> | ||||
|         <dependency> | ||||
|             <groupId>org.codehaus.groovy</groupId> | ||||
|             <artifactId>groovy-json</artifactId> | ||||
|             <version>3.0.22</version> | ||||
|             <version>3.0.25</version> | ||||
|         </dependency> | ||||
|  | ||||
|        <dependency> | ||||
|   | ||||
| @@ -675,6 +675,11 @@ public class RestWrapper extends DSLWrapper<RestWrapper> | ||||
|         { | ||||
|             returnedResponse = onRequest().get(restRequest.getPath(), restRequest.getPathParams()).andReturn(); | ||||
|         } | ||||
|         else if (HttpMethod.PATCH.equals(httpMethod)) | ||||
|         { | ||||
|             returnedResponse = onRequest().body(restRequest.getBody()) | ||||
|                     .patch(restRequest.getPath(), restRequest.getPathParams()).andReturn(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             returnedResponse = onRequest().get(restRequest.getPath(), restRequest.getPathParams()).andReturn(); | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2005 - 2022 Alfresco Software Limited | ||||
|  * Copyright (C) 2005 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
| @@ -747,7 +747,7 @@ public class CreateRulesTests extends RulesRestTest | ||||
|                 .createSingleRule(ruleModel); | ||||
|  | ||||
|         restClient.assertStatusCodeIs(NOT_FOUND); | ||||
|         restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found"); | ||||
|         restClient.assertLastError().containsSummary("Destination folder having Id: non-existent-node no longer exists. Please update your rule definition."); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -0,0 +1,95 @@ | ||||
| /* | ||||
|  * #%L | ||||
|  * Alfresco Repository | ||||
|  * %% | ||||
|  * Copyright (C) 2025 - 2025 Alfresco Software Limited | ||||
|  * %% | ||||
|  * This file is part of the Alfresco software. | ||||
|  * If the software was purchased under a paid Alfresco license, the terms of | ||||
|  * the paid license agreement will prevail.  Otherwise, the software is | ||||
|  * provided under the following open source license terms: | ||||
|  * | ||||
|  * Alfresco is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Lesser General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Alfresco is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public License | ||||
|  * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * #L% | ||||
|  */ | ||||
|  | ||||
| package org.alfresco.rest.search; | ||||
|  | ||||
| import static org.testng.Assert.*; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.commons.collections.CollectionUtils; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.testng.annotations.Test; | ||||
|  | ||||
| import org.alfresco.rest.RestTest; | ||||
| import org.alfresco.rest.model.RestNodeModel; | ||||
| import org.alfresco.utility.RetryOperation; | ||||
| import org.alfresco.utility.Utility; | ||||
| import org.alfresco.utility.model.ContentModel; | ||||
| import org.alfresco.utility.model.FileModel; | ||||
| import org.alfresco.utility.model.TestGroup; | ||||
| import org.alfresco.utility.model.UserModel; | ||||
| import org.alfresco.utility.testrail.ExecutionType; | ||||
| import org.alfresco.utility.testrail.annotation.TestRail; | ||||
|  | ||||
| public class NodeContentTest extends RestTest | ||||
| { | ||||
|  | ||||
|     @TestRail(section = {TestGroup.REST_API, | ||||
|             TestGroup.SEARCH}, executionType = ExecutionType.SANITY, description = "Check basic functionality of GET queries/sites") | ||||
|     @Test(groups = {TestGroup.REST_API, TestGroup.RATINGS, TestGroup.CORE}) | ||||
|     public void testNodeContent() throws Exception | ||||
|     { | ||||
|  | ||||
|         UserModel adminUser = dataContent.getAdminUser(); | ||||
|         final String fileName = "nodecontent.pdf"; | ||||
|         final String term = "babekyrtso"; | ||||
|  | ||||
|         FileModel fileModel = FileModel.getFileModelBasedOnTestDataFile(fileName); | ||||
|         restClient.authenticateUser(adminUser) | ||||
|                 .configureRequestSpec() | ||||
|                 .addMultiPart("filedata", fileModel.toFile()); | ||||
|         RestNodeModel node = restClient.authenticateUser(adminUser).withCoreAPI().usingNode(ContentModel.my()).createNode(); | ||||
|         restClient.assertStatusCodeIs(HttpStatus.CREATED); | ||||
|  | ||||
|         SearchRequest query = new SearchRequest(); | ||||
|         RestRequestQueryModel queryModel = new RestRequestQueryModel(); | ||||
|         queryModel.setLanguage("afts"); | ||||
|         queryModel.setQuery(term); | ||||
|         query.setQuery(queryModel); | ||||
|  | ||||
|         RetryOperation op = () -> { | ||||
|             List<SearchNodeModel> entries = restClient.authenticateUser(adminUser) | ||||
|                     .withSearchAPI() | ||||
|                     .search(query).getEntries(); | ||||
|  | ||||
|             assertFalse(CollectionUtils.isEmpty(entries), "Search results should not be empty"); | ||||
|             boolean fileFound = entries.stream() | ||||
|                     .map(SearchNodeModel::getModel) | ||||
|                     .anyMatch(e -> fileName.equals(e.getName())); | ||||
|             assertTrue(fileFound, "Search results should contain the file: " + fileName); | ||||
|  | ||||
|             restClient.assertStatusCodeIs(HttpStatus.OK); | ||||
|         }; | ||||
|         Utility.sleep(300, 100000, op); | ||||
|  | ||||
|         restClient.authenticateUser(adminUser) | ||||
|                 .withCoreAPI() | ||||
|                 .usingNode(ContentModel.my()) | ||||
|                 .deleteNode(node); | ||||
|         restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT); | ||||
|     } | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
							
								
								
									
										
											BIN
										
									
								
								packaging/tests/tas-restapi/src/test/resources/shared-resources/testdata/nodecontent.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packaging/tests/tas-restapi/src/test/resources/shared-resources/testdata/nodecontent.pdf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -15,6 +15,7 @@ | ||||
|             <package name="org.alfresco.rest.people.*"/> | ||||
|             <package name="org.alfresco.rest.queries.*"/> | ||||
|             <package name="org.alfresco.rest.ratings.*"/> | ||||
|             <package name="org.alfresco.rest.search.*"/> | ||||
|         </packages> | ||||
|     </test> | ||||
| </suite> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-tests</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <developers> | ||||
| @@ -31,11 +31,6 @@ | ||||
|             <artifactId>webdav</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|  | ||||
|     <build> | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| com.epam.reportportal.testng.ReportPortalTestNGListener | ||||
| @@ -7,7 +7,7 @@ | ||||
|     <parent> | ||||
|         <groupId>org.alfresco</groupId> | ||||
|         <artifactId>alfresco-community-repo-packaging</artifactId> | ||||
|         <version>25.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <properties> | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
|   <!-- Resource defaultTransactionIsolation="-1" defaultAutoCommit="false" maxActive="100" initialSize="10" password="alfresco" username="alfresco" url="jdbc:mysql:///alfresco" driverClassName="org.gjt.mm.mysql.Driver" type="javax.sql.DataSource" auth="Container" name="jdbc/dataSource"/--> | ||||
|   <Environment override="false" type="java.lang.Boolean" name="properties/startup.enable" description="A flag that globally enables or disables startup of the major Alfresco subsystems." value="true"/> | ||||
|   <Environment override="false" type="java.lang.String" name="properties/dir.root" description="The filesystem directory below which content and index data is stored. Should be on a shared disk if this is a clustered installation."/> | ||||
|   <Environment override="false" type="java.lang.String" name="properties/hibernate.dialect" description="The fully qualified name of a org.hibernate.dialect.Dialect subclass that allows Hibernate to generate SQL optimized for a particular relational database. Choose from org.hibernate.dialect.DerbyDialect, org.hibernate.dialect.MySQLInnoDBDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect, org.hibernate.dialect.PostgreSQLDialect"/> | ||||
|   <Environment override="false" type="java.lang.String" name="properties/hibernate.dialect" description="The fully qualified name of a org.hibernate.dialect.Dialect subclass that allows Hibernate to generate SQL optimized for a particular relational database. Choose from org.hibernate.dialect.DerbyDialect, org.hibernate.dialect.MySQLInnoDBDialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect, org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect, org.alfresco.repo.domain.hibernate.dialect.SQLServerDialect, org.hibernate.dialect.PostgreSQLDialect"/> | ||||
|   <Environment override="false" type="java.lang.String" name="properties/hibernate.query.substitutions" description="Mapping from tokens in Hibernate queries to SQL tokens. For PostgreSQL, set this to "true TRUE, false FALSE"."/> | ||||
|   <Environment override="false" type="java.lang.Boolean" name="properties/hibernate.jdbc.use_get_generated_keys" description="Enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve natively generated keys after insert. Requires JDBC3+ driver. Set to false if your driver has problems with the Hibernate identifier generators. By default, tries to determine the driver capabilities using connection metadata."/> | ||||
|   <Environment override="false" type="java.lang.String" name="properties/hibernate.default_schema" description="Qualify unqualified table names with the given schema/tablespace in generated SQL. It may be necessary to set this when the target database has more than one schema."/> | ||||
|   | ||||
| @@ -500,7 +500,7 @@ | ||||
|          org.hibernate.dialect.MySQLInnoDBDialect, | ||||
|          org.alfresco.repo.domain.hibernate.dialect.AlfrescoOracle9Dialect, | ||||
|          org.alfresco.repo.domain.hibernate.dialect.AlfrescoSybaseAnywhereDialect, | ||||
|          org.alfresco.repo.domain.hibernate.dialect.AlfrescoSQLServerDialect, org.hibernate.dialect.PostgreSQLDialect</description> | ||||
|          org.alfresco.repo.domain.hibernate.dialect.SQLServerDialect, org.hibernate.dialect.PostgreSQLDialect</description> | ||||
|       <env-entry-name>properties/hibernate.dialect</env-entry-name> | ||||
|       <env-entry-type>java.lang.String</env-entry-type> | ||||
|       <env-entry-value/> <!-- Empty value included for JBoss compatibility --> | ||||
|   | ||||
							
								
								
									
										110
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>alfresco-community-repo</artifactId> | ||||
|     <version>25.2.0.13</version> | ||||
|     <version>25.3.0.63</version> | ||||
|     <packaging>pom</packaging> | ||||
|     <name>Alfresco Community Repo Parent</name> | ||||
|  | ||||
| @@ -24,7 +24,7 @@ | ||||
|  | ||||
|     <properties> | ||||
|         <acs.version.major>25</acs.version.major> | ||||
|         <acs.version.minor>2</acs.version.minor> | ||||
|         <acs.version.minor>3</acs.version.minor> | ||||
|         <acs.version.revision>0</acs.version.revision> | ||||
|         <acs.version.label /> | ||||
|         <amp.min.version>${acs.version.major}.0.0</amp.min.version> | ||||
| @@ -51,41 +51,42 @@ | ||||
|         <dependency.alfresco-server-root.version>7.0.2</dependency.alfresco-server-root.version> | ||||
|         <dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version> | ||||
|         <dependency.activiti.version>5.23.0</dependency.activiti.version> | ||||
|         <dependency.alfresco-transform-core.version>5.1.7</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.1.7</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-transform-core.version>5.2.2</dependency.alfresco-transform-core.version> | ||||
|         <dependency.alfresco-transform-service.version>4.2.2</dependency.alfresco-transform-service.version> | ||||
|         <dependency.alfresco-greenmail.version>7.1</dependency.alfresco-greenmail.version> | ||||
|         <dependency.acs-event-model.version>1.0.2</dependency.acs-event-model.version> | ||||
|         <dependency.acs-event-model.version>1.0.11</dependency.acs-event-model.version> | ||||
|  | ||||
|         <dependency.aspectj.version>1.9.22.1</dependency.aspectj.version> | ||||
|         <dependency.spring.version>6.2.2</dependency.spring.version> | ||||
|         <dependency.spring-security.version>6.3.7</dependency.spring-security.version> | ||||
|         <dependency.spring.version>6.2.11</dependency.spring.version> | ||||
|         <dependency.spring-security.version>6.4.11</dependency.spring-security.version> | ||||
|         <dependency.antlr.version>3.5.3</dependency.antlr.version> | ||||
|         <dependency.jackson.version>2.17.2</dependency.jackson.version> | ||||
|         <dependency.cxf.version>4.1.0</dependency.cxf.version> | ||||
|         <dependency.cxf.version>4.1.2</dependency.cxf.version> | ||||
|         <dependency.opencmis.version>1.0.0-jakarta-1</dependency.opencmis.version> | ||||
|         <dependency.webscripts.version>10.0</dependency.webscripts.version> | ||||
|         <dependency.bouncycastle.version>1.79</dependency.bouncycastle.version> | ||||
|         <dependency.mockito-core.version>5.14.1</dependency.mockito-core.version> | ||||
|         <dependency.webscripts.version>10.2</dependency.webscripts.version> | ||||
|         <dependency.bouncycastle.version>1.81</dependency.bouncycastle.version> | ||||
|         <dependency.mockito-core.version>5.18.0</dependency.mockito-core.version> | ||||
|         <dependency.assertj.version>3.27.3</dependency.assertj.version> | ||||
|         <dependency.org-json.version>20240303</dependency.org-json.version> | ||||
|         <dependency.org-json.version>20250517</dependency.org-json.version> | ||||
|         <dependency.commons-dbcp.version>2.12.0</dependency.commons-dbcp.version> | ||||
|         <dependency.commons-io.version>2.18.0</dependency.commons-io.version> | ||||
|         <dependency.gson.version>2.12.1</dependency.gson.version> | ||||
|         <dependency.commons-io.version>2.20.0</dependency.commons-io.version> | ||||
|         <dependency.gson.version>2.13.1</dependency.gson.version> | ||||
|         <dependency.guava.version>33.3.1-jre</dependency.guava.version> | ||||
|         <dependency.httpclient.version>4.5.14</dependency.httpclient.version> | ||||
|         <dependency.httpcore.version>4.4.16</dependency.httpcore.version> | ||||
|         <dependency.httpcomponents-httpclient5.version>5.4.1</dependency.httpcomponents-httpclient5.version> | ||||
|         <dependency.httpcomponents-httpcore5.version>5.3.3</dependency.httpcomponents-httpcore5.version> | ||||
|         <dependency.httpcomponents-httpclient5.version>5.5</dependency.httpcomponents-httpclient5.version> | ||||
|         <dependency.httpcomponents-httpcore5.version>5.3.4</dependency.httpcomponents-httpcore5.version> | ||||
|         <dependency.httpcomponents-httpcore5-h2.version>5.3.4</dependency.httpcomponents-httpcore5-h2.version> | ||||
|         <dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version> | ||||
|         <dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version> | ||||
|         <dependency.slf4j.version>2.0.16</dependency.slf4j.version> | ||||
|         <dependency.log4j.version>2.24.3</dependency.log4j.version> | ||||
|         <dependency.groovy.version>3.0.23</dependency.groovy.version> | ||||
|         <dependency.tika.version>2.9.2</dependency.tika.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.truezip.version>7.7.10</dependency.truezip.version> | ||||
|         <dependency.poi.version>5.3.0</dependency.poi.version> | ||||
|         <dependency.poi.version>5.4.0</dependency.poi.version> | ||||
|         <dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version> | ||||
|         <dependency.camel.version>4.6.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies --> | ||||
|         <dependency.camel.version>4.11.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies --> | ||||
|         <dependency.netty.version>4.1.118.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common --> | ||||
|         <dependency.activemq.version>5.18.6</dependency.activemq.version> | ||||
|         <dependency.apache-compress.version>1.27.1</dependency.apache-compress.version> | ||||
| @@ -114,19 +115,19 @@ | ||||
|         <dependency.jakarta-json-path.version>2.9.0</dependency.jakarta-json-path.version> | ||||
|         <dependency.json-smart.version>2.5.2</dependency.json-smart.version> | ||||
|         <alfresco.googledrive.version>4.1.0</alfresco.googledrive.version> | ||||
|         <alfresco.aos-module.version>3.3.0-A1</alfresco.aos-module.version> | ||||
|         <alfresco.api-explorer.version>25.1.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share --> | ||||
|         <alfresco.aos-module.version>3.4.0</alfresco.aos-module.version> | ||||
|         <alfresco.api-explorer.version>25.2.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share --> | ||||
|  | ||||
|         <alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version> | ||||
|         <license-maven-plugin.version>2.4.0</license-maven-plugin.version> | ||||
|         <spotless-plugin.version>2.44.2</spotless-plugin.version> | ||||
|         <spotless-plugin.version>2.45.0</spotless-plugin.version> | ||||
|  | ||||
|         <dependency.postgresql.version>42.7.5</dependency.postgresql.version> | ||||
|         <dependency.mysql.version>8.0.30</dependency.mysql.version> | ||||
|         <dependency.mysql-image.version>8</dependency.mysql-image.version> | ||||
|         <dependency.mariadb.version>2.7.4</dependency.mariadb.version> | ||||
|         <dependency.tas-utility.version>5.0.2</dependency.tas-utility.version> | ||||
|         <dependency.rest-assured.version>5.5.0</dependency.rest-assured.version> | ||||
|         <dependency.rest-assured.version>5.5.5</dependency.rest-assured.version> | ||||
|         <dependency.tas-email.version>2.0.0</dependency.tas-email.version> | ||||
|         <dependency.tas-webdav.version>1.21</dependency.tas-webdav.version> | ||||
|         <dependency.tas-ftp.version>1.19</dependency.tas-ftp.version> | ||||
| @@ -153,7 +154,7 @@ | ||||
|         <connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection> | ||||
|         <developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection> | ||||
|         <url>https://github.com/Alfresco/alfresco-community-repo</url> | ||||
|         <tag>25.2.0.13</tag> | ||||
|         <tag>25.3.0.63</tag> | ||||
|     </scm> | ||||
|  | ||||
|     <distributionManagement> | ||||
| @@ -169,6 +170,12 @@ | ||||
|  | ||||
|     <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> | ||||
| @@ -400,15 +407,20 @@ | ||||
|                 <artifactId>httpcore5</artifactId> | ||||
|                 <version>${dependency.httpcomponents-httpcore5.version}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>org.apache.httpcomponents.core5</groupId> | ||||
|                 <artifactId>httpcore5-h2</artifactId> | ||||
|                 <version>${dependency.httpcomponents-httpcore5-h2.version}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-logging</groupId> | ||||
|                 <artifactId>commons-logging</artifactId> | ||||
|                 <version>1.3.3</version> | ||||
|                 <version>1.3.5</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-beanutils</groupId> | ||||
|                 <artifactId>commons-beanutils</artifactId> | ||||
|                 <version>1.9.4</version> | ||||
|                 <version>1.11.0</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-codec</groupId> | ||||
| @@ -416,9 +428,9 @@ | ||||
|                 <version>1.18.0</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-lang</groupId> | ||||
|                 <artifactId>commons-lang</artifactId> | ||||
|                 <version>2.6</version> | ||||
|                 <groupId>org.apache.commons</groupId> | ||||
|                 <artifactId>commons-lang3</artifactId> | ||||
|                 <version>3.18.0</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-io</groupId> | ||||
| @@ -438,8 +450,8 @@ | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>org.apache.commons</groupId> | ||||
|                 <artifactId>commons-fileupload2-jakarta</artifactId> | ||||
|                 <version>2.0.0-M1</version> | ||||
|                 <artifactId>commons-fileupload2-jakarta-servlet6</artifactId> | ||||
|                 <version>2.0.0-M4</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>commons-net</groupId> | ||||
| @@ -702,13 +714,13 @@ | ||||
|             <dependency> | ||||
|                 <groupId>com.networknt</groupId> | ||||
|                 <artifactId>json-schema-validator</artifactId> | ||||
|                 <version>1.5.5</version> | ||||
|                 <version>1.5.8</version> | ||||
|             </dependency> | ||||
|             <!-- upgrade dependency from TIKA --> | ||||
|             <dependency> | ||||
|                 <groupId>org.jsoup</groupId> | ||||
|                 <artifactId>jsoup</artifactId> | ||||
|                 <version>1.18.1</version> | ||||
|                 <version>1.21.1</version> | ||||
|             </dependency> | ||||
|             <!-- upgrade dependency from TIKA --> | ||||
|             <dependency> | ||||
| @@ -792,7 +804,7 @@ | ||||
|             <dependency> | ||||
|                 <groupId>joda-time</groupId> | ||||
|                 <artifactId>joda-time</artifactId> | ||||
|                 <version>2.13.1</version> | ||||
|                 <version>2.14.0</version> | ||||
|             </dependency> | ||||
|  | ||||
|             <!-- provided dependencies --> | ||||
| @@ -822,18 +834,6 @@ | ||||
|                 <version>4.13.2</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>com.epam.reportportal</groupId> | ||||
|                 <artifactId>agent-java-testng</artifactId> | ||||
|                 <version>5.4.0</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>com.squareup.okhttp3</groupId> | ||||
|                 <artifactId>okhttp</artifactId> | ||||
|                 <version>4.12.0</version> | ||||
|                 <scope>test</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>org.antlr</groupId> | ||||
|                 <artifactId>gunit</artifactId> | ||||
| @@ -949,7 +949,7 @@ | ||||
|             <dependency> | ||||
|                 <groupId>org.projectlombok</groupId> | ||||
|                 <artifactId>lombok</artifactId> | ||||
|                 <version>1.18.36</version> | ||||
|                 <version>1.18.38</version> | ||||
|                 <scope>provided</scope> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
| @@ -1006,7 +1006,7 @@ | ||||
|                 <plugin> | ||||
|                     <groupId>io.fabric8</groupId> | ||||
|                     <artifactId>docker-maven-plugin</artifactId> | ||||
|                     <version>0.45.0</version> | ||||
|                     <version>0.46.0</version> | ||||
|                 </plugin> | ||||
|                 <plugin> | ||||
|                     <artifactId>maven-surefire-plugin</artifactId> | ||||
| @@ -1087,7 +1087,7 @@ | ||||
|                 <plugin> | ||||
|                     <groupId>org.codehaus.cargo</groupId> | ||||
|                     <artifactId>cargo-maven3-plugin</artifactId> | ||||
|                     <version>1.10.16</version> | ||||
|                     <version>1.10.20</version> | ||||
|                 </plugin> | ||||
|                 <plugin> | ||||
|                     <groupId>org.apache.maven.plugins</groupId> | ||||
| @@ -1131,16 +1131,10 @@ | ||||
|                                             <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</exclude> | ||||
|                                             <exclude>org.bouncycastle:(,1.81)</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.2.0.13</version> | ||||
|         <version>25.3.0.63</version> | ||||
|     </parent> | ||||
|  | ||||
|     <dependencies> | ||||
| @@ -45,7 +45,7 @@ | ||||
|         <dependency> | ||||
|             <groupId>org.apache.santuario</groupId> | ||||
|             <artifactId>xmlsec</artifactId> | ||||
|             <version>4.0.3</version> | ||||
|             <version>4.0.4</version> | ||||
|         </dependency> | ||||
|         <!-- newer version, see REPO-3133 --> | ||||
|         <dependency> | ||||
| @@ -66,11 +66,6 @@ | ||||
|             <artifactId>junit</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.epam.reportportal</groupId> | ||||
|             <artifactId>agent-java-testng</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.mockito</groupId> | ||||
|             <artifactId>mockito-core</artifactId> | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user