Compare commits

..

186 Commits

Author SHA1 Message Date
Travis CI User
06871bce8a [maven-release-plugin][skip ci] prepare for next development iteration 2022-12-07 13:42:14 +00:00
Travis CI User
58e595ce13 [maven-release-plugin][skip ci] prepare release 18.7 2022-12-07 13:42:11 +00:00
tiagosalvado10
333a7dca98 [MNT-22437] Remove ACS version from landing page (#1480) (#1605)
* [MNT-22437] Remove ACS version from landing page

* [MNT-22437] Bump surf-webscripts to 8.33

(cherry picked from commit ace4691540)
2022-12-07 12:59:49 +00:00
Travis CI User
0c810f5e80 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-29 12:07:13 +00:00
Travis CI User
4d930a6f18 [maven-release-plugin][skip ci] prepare release 18.6 2022-11-29 12:07:10 +00:00
evasques
ff68f92455 MNT-23108 - Manage contentStream resource closure in RemoteTransformerClient request (#1559) (#1564)
* Manage contentStream resource closure so we don't have connections hanging when we lose connection to AIO

(cherry picked from commit 783efca1d2)
2022-11-29 10:46:53 +00:00
Travis CI User
c88353ccb7 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-21 10:33:58 +00:00
Travis CI User
6b94ee41d4 [maven-release-plugin][skip ci] prepare release 18.5 2022-11-21 10:33:56 +00:00
rrajoria
a414aa3064 MNT-23204: Group Search (#1558)
(cherry picked from commit 93a7790d44)
2022-11-21 15:18:58 +05:30
Travis CI User
7914e87f77 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-11 23:56:44 +00:00
Travis CI User
4f63b3871e [maven-release-plugin][skip ci] prepare release 18.4 2022-11-11 23:56:41 +00:00
tiagosalvado10
876962db57 [MNT-23158] Scripts limits configuration and optimization (#1519) (#1548)
(cherry picked from commit f391cfa38c)
2022-11-11 23:19:15 +00:00
Travis CI User
5e2ff120ae [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-11 22:23:29 +00:00
Travis CI User
2d95ccc754 [maven-release-plugin][skip ci] prepare release 18.3 2022-11-11 22:23:26 +00:00
Antonio Felix
3de741a78e MNT-23276 - The null facet name should be considered (#1540) (#1550)
(cherry picked from commit 295a8f7ba2)
2022-11-11 21:47:55 +00:00
Travis CI User
8993ec9d5c [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-11 16:24:16 +00:00
Travis CI User
428a82c195 [maven-release-plugin][skip ci] prepare release 18.2 2022-11-11 16:24:13 +00:00
Vítor Moreira
519ef19c83 MNT-22485: audit query with createdAt criteria returns correct totalI… (#1545)
* MNT-22485: audit query with createdAt criteria returns correct totalI… (#1535)
(cherry picked from commit 14572d328f)

* MNT-22485: added missing tables to query (#1547)
(cherry picked from commit 7f6bd86b0c)
2022-11-11 10:35:44 +00:00
Travis CI User
f19849b547 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-27 11:08:49 +00:00
Travis CI User
d956a4f4aa [maven-release-plugin][skip ci] prepare release 18.1 2022-10-27 11:08:46 +00:00
Krystian Dabrowski
71f649d1bd Create ServicePack branch release/7.3.N 2022-10-27 12:25:07 +02:00
Travis CI User
55faedde51 [maven-release-plugin][skip ci] prepare release 17.183 2022-10-25 13:08:31 +00:00
Elia Porciani
32a524eb1f Revert "Fix/acs 2699 mandatory modifier (#1472)" (#1520)
[ACS-3854] This reverts commit 75acf5110e.
2022-10-25 14:16:26 +02:00
Travis CI User
105702bf09 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-24 12:57:27 +00:00
Travis CI User
9e2e00c4a8 [maven-release-plugin][skip ci] prepare release 17.182 2022-10-24 12:57:24 +00:00
krdabrowski
e79eac4fd8 ACS-3689: Release API explorer (Final) 7.3.0 (#1518) 2022-10-24 14:19:58 +02:00
dependabot[bot]
20f9cfc42d Bump api-explorer from 7.3.0-A1 to 7.3.0 (#1517)
Bumps [api-explorer](https://github.com/Alfresco/rest-api-explorer) from 7.3.0-A1 to 7.3.0.
- [Release notes](https://github.com/Alfresco/rest-api-explorer/releases)
- [Commits](https://github.com/Alfresco/rest-api-explorer/compare/7.3.0-A1...7.3.0)

---
updated-dependencies:
- dependency-name: org.alfresco:api-explorer
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 14:33:17 +03:00
Travis CI User
5baee04dcc [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-23 00:13:01 +00:00
Travis CI User
f821756021 [maven-release-plugin][skip ci] prepare release 17.181 2022-10-23 00:12:58 +00:00
Alfresco CI User
ae68b517f1 [force] Force release for 2022-10-23. 2022-10-23 00:05:45 +00:00
Travis CI User
24b249d93d [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-21 17:04:37 +00:00
Travis CI User
5d9b11d121 [maven-release-plugin][skip ci] prepare release 17.180 2022-10-21 17:04:35 +00:00
Tom Page
902f3b5275 ACS-3793 Permissions tests for creating rules. (#1513)
* ACS-3793 Permissions tests for creating rules.

* ACS-3793 Include Test annotation in new permissions tests.

* ACS-3793: Changing the way permissions are updated.

Co-authored-by: mpichura <maciej.pichura@hyland.com>
2022-10-21 13:17:58 +02:00
Travis CI User
3801ed4d99 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-21 06:06:12 +00:00
Travis CI User
382a4799ae [maven-release-plugin][skip ci] prepare release 17.179 2022-10-21 06:06:09 +00:00
MohinishSah
67c44a934d Updated AOS and Google docs final version 2022-10-21 10:59:34 +05:30
Travis CI User
35a364beaa [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-20 18:15:31 +00:00
Travis CI User
68ed04cc6d [maven-release-plugin][skip ci] prepare release 17.178 2022-10-20 18:15:29 +00:00
MohinishSah
dc52bc107d [skip tests] 2022-10-20 23:38:14 +05:30
kcichonczyk
ff110af9b3 InsightEngine version updated to 2.0.5 (ACS-3679) (#1514) 2022-10-20 18:45:24 +02:00
Travis CI User
87b2e0f060 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-20 13:36:36 +00:00
Travis CI User
fd9d47826e [maven-release-plugin][skip ci] prepare release 17.177 2022-10-20 13:36:32 +00:00
Tom Page
6e31f713f0 ACS-3652 Script node validation. (#1507)
* ACS-3652 Add validation for individual actions.

In particular write access is required for the folder specified in the copy and move actions.

* ACS-3652: Adding action validations for node permissions.

* ACS-3652: Fixing failing E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652 E2E tests for script validation.

* ACS-3652 Fix script validation test to use admin.

* ACS-3652: Removing unnecessary code.

* ACS-3652 E2Es for link to category action.

* ACS-3652 Fix test case for normal user using script in rule.

* ACS-3652: Adding applicable action definition check.

* ACS-3652: Adding more thorough action definition checks and fixing node permission and type checks.

* ACS-3652: Adding more thorough E2E tests and some fixes.

* ACS-3652: Adding more E2E tests and some fixes.

* ACS-3652: Fixing some missing corner cases, adding tests.

* ACS-3652: Small refactoring after code review.

Co-authored-by: mpichura <maciej.pichura@hyland.com>
2022-10-20 14:00:14 +01:00
Maciej Pichura
7a70b40cc0 ACS-3652 Node access validation for Rule Action Parameters, ACS-3795 Validate that action is suitable for use in rule (#1502)
* ACS-3652 Add validation for individual actions.

In particular write access is required for the folder specified in the copy and move actions.

* ACS-3652: Adding action validations for node permissions.

* ACS-3652: Fixing failing E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652 E2E tests for script validation.

* ACS-3652 Fix script validation test to use admin.

* ACS-3652: Removing unnecessary code.

* ACS-3652 E2Es for link to category action.

* ACS-3652: Adding applicable action definition check.

* ACS-3652: Adding more thorough action definition checks and fixing node permission and type checks.

* ACS-3652: Adding more thorough E2E tests and some fixes.

* ACS-3652: Adding more E2E tests and some fixes.

* ACS-3652: Fixing some missing corner cases, adding tests.

* ACS-3652: Small refactoring after code review.

Co-authored-by: Tom Page <thomas.page@alfresco.com>
2022-10-20 14:39:29 +02:00
Travis CI User
96c437e6a4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-20 09:34:39 +00:00
Travis CI User
6e4a7c1866 [maven-release-plugin][skip ci] prepare release 17.176 2022-10-20 09:34:37 +00:00
Kacper Magdziarz
b72cf6f267 Upgrade to latest ATS components (#1511) 2022-10-20 10:58:02 +02:00
Travis CI User
f65fc31601 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-20 07:05:30 +00:00
Travis CI User
4697e7bac2 [maven-release-plugin][skip ci] prepare release 17.175 2022-10-20 07:05:26 +00:00
MohinishSah
50455c8730 Updating Google drive version A2 2022-10-20 11:38:07 +05:30
Maciej Pichura
2fac4d8a9b ACS-3788: Handling null/empty rule action parameter values. (#1505)
* ACS-3788: Handling null rule action parameter values.

* ACS-3788: Throwing exception when empty/null rule action parameter values.
2022-10-19 15:09:22 +02:00
Travis CI User
7a300dc9c9 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-18 03:51:49 +00:00
Travis CI User
a996cf1842 [maven-release-plugin][skip ci] prepare release 17.174 2022-10-18 03:51:46 +00:00
MohinishSah
1d9d6ad0bb updating AOS alpha version A7 2022-10-17 23:35:20 +05:30
Travis CI User
8ba67497e1 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-17 16:54:14 +00:00
Travis CI User
fd889628c6 [maven-release-plugin][skip ci] prepare release 17.173 2022-10-17 16:54:11 +00:00
Maciej Pichura
50b9f5c612 ACS-3759: Fixing bug for empty action parameter values (#1501)
* ACS-3759: Fixing bug for empty action parameter values

* ACS-3759: Fixing missing import
2022-10-17 18:07:32 +02:00
Travis CI User
e6bdd5738c [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-16 00:12:16 +00:00
Travis CI User
4bf29ca69c [maven-release-plugin][skip ci] prepare release 17.172 2022-10-16 00:12:13 +00:00
Alfresco CI User
f4f5fd4182 [force] Force release for 2022-10-16. 2022-10-16 00:05:13 +00:00
Travis CI User
dfb6f50056 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-15 11:15:03 +00:00
Travis CI User
c7227d19c4 [maven-release-plugin][skip ci] prepare release 17.171 2022-10-15 11:15:01 +00:00
MohinishSah
9b779facd9 updating Aos alpha version A6 2022-10-15 16:10:29 +05:30
MohinishSah
f64d0a1b59 Update pom.xml 2022-10-15 15:41:59 +05:30
MohinishSah
8974845671 Merge pull request #1500 from Alfresco/fix/test-aos
Fix/test aos
2022-10-15 12:39:18 +05:30
MohinishSah
a7ae83bbee Update pom.xml 2022-10-15 12:02:09 +05:30
Jared Ottley
ee1ac25bf6 Test AOS version 1.5.0-A4 2022-10-14 13:22:07 -06:00
Travis CI User
8757f0ff2b [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-14 16:28:19 +00:00
Travis CI User
37f5b637dd [maven-release-plugin][skip ci] prepare release 17.170 2022-10-14 16:28:16 +00:00
Tom Page
b369538a61 ACS-3651 Update rule util initialisation to be on request.
This avoids creating data before env is ready and in cases where we want an ootb repo.
2022-10-14 16:37:58 +01:00
Travis CI User
1f844ce199 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-14 14:05:20 +00:00
Travis CI User
6eb80bf64e [maven-release-plugin][skip ci] prepare release 17.169 2022-10-14 14:05:17 +00:00
rrajoria
2ab1023eb7 Reverting AOS Dependency 2022-10-14 18:59:36 +05:30
rrajoria
fe1233791d Updating GoogleDrive and AOS Dependencies 2022-10-14 18:44:52 +05:30
Travis CI User
d1079890f7 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-14 10:32:32 +00:00
Travis CI User
2660da2dcb [maven-release-plugin][skip ci] prepare release 17.168 2022-10-14 10:32:29 +00:00
mikolajbrzezinski
4f3382fd92 update ooxml schemas to poi-ooxml-lite (#1498) 2022-10-14 11:57:04 +02:00
Tom Page
86a213541f Merge pull request #1497 from Alfresco/feature/ACS-3651_NodeValidation
ACS-3651 Validate node pameters.
2022-10-14 09:25:55 +01:00
Tom Page
fd83b72226 Merge pull request #1496 from Alfresco/feature/ACS-3651_RulesUtilService
ACS-3651 Convert RulesTestsUtils to a service bean.
2022-10-14 09:25:20 +01:00
Tom Page
1d0dcf3e15 ACS-3651 Remove unused reference to node service. 2022-10-13 15:37:56 +01:00
Tom Page
38bff5dc82 ACS-3651 Add unit tests for node exists and read permission. 2022-10-13 15:01:41 +01:00
Travis CI User
7b026de665 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-13 13:14:50 +00:00
Travis CI User
983de15f72 [maven-release-plugin][skip ci] prepare release 17.167 2022-10-13 13:14:47 +00:00
Tom Page
9b8b1bbbe6 ACS-3651 Validate node pameters. 2022-10-13 14:05:12 +01:00
Tom Page
5aeb9c932a Merge branch 'master' into feature/ACS-3651_RulesUtilService 2022-10-13 13:29:40 +01:00
Tom Page
32aa786c3f ACS-3651 Convert RulesTestsUtils to a service bean.
Update a few dummy folder nodes to use real folders.
2022-10-13 11:51:45 +01:00
Maciej Pichura
1759364b50 ACS-3723, ACS-3724, ACS-3725 move rules V1 API to private space (#1495)
* ACS-3723: Moving endpoints to private API path.

* ACS-3723: Fixes to E2E tests and some other parts.

* ACS-3723: Removing unnecessary imports.
2022-10-13 12:38:44 +02:00
Travis CI User
2ecb64628e [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-13 08:19:55 +00:00
Travis CI User
1fb4ab3bb8 [maven-release-plugin][skip ci] prepare release 17.166 2022-10-13 08:19:52 +00:00
Sara
771e4bb88b ACS-2579 Bump freemarker to 2.3.31-alfresco-patched (#1492) 2022-10-13 09:12:12 +02:00
Travis CI User
6cd05f9845 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-13 05:01:11 +00:00
Travis CI User
1bafb3006c [maven-release-plugin][skip ci] prepare release 17.165 2022-10-13 05:01:08 +00:00
MohinishSah
96c185c25f Merge pull request #1486 from Alfresco/fix/PRODSEC-6265_New
Handle XSS
2022-10-13 09:50:51 +05:30
Travis CI User
94f99bf0fa [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-12 16:12:18 +00:00
Travis CI User
fa0e90e267 [maven-release-plugin][skip ci] prepare release 17.164 2022-10-12 16:12:15 +00:00
Piotr Żurek
9c0799b49a ACS-2579 Use vanilla freemarker (#1491) 2022-10-12 17:12:35 +02:00
mstrankowski
1bbaf470a7 Update transform-core to 3.0.0-A6
Update transform-service to 2.0.0-A5
2022-10-12 16:12:01 +03:00
Travis CI User
7fe4c82adb [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-12 05:34:15 +00:00
Travis CI User
aed31a98e3 [maven-release-plugin][skip ci] prepare release 17.163 2022-10-12 05:34:13 +00:00
kcichonczyk
1f7987469b [ACS-3678] updated InsightEngine version to 2.0.5-A2 (#1489) 2022-10-11 22:26:20 +02:00
Travis CI User
96e176b83e [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 15:56:15 +00:00
Travis CI User
de14eb97cb [maven-release-plugin][skip ci] prepare release 17.162 2022-10-11 15:56:11 +00:00
krdabrowski
8ff074dfea ACS-3620: E2Es - API for manual triggering rules on a folder (#1482)
- adding "alwaysRun = true" to @BeforeMethod due to failing acs-packaging "REST API TAS tests with AIMS"
2022-10-11 17:14:43 +02:00
Travis CI User
a27a5571bc [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 14:31:41 +00:00
Travis CI User
3f9b18d110 [maven-release-plugin][skip ci] prepare release 17.161 2022-10-11 14:31:38 +00:00
Tom Page
623d166a76 Merge pull request #1487 from Alfresco/feature/ACS-3595_ActionParamMap
ACS-3651 Use Serializable for values in action parameters.
2022-10-11 14:53:02 +01:00
Travis CI User
6502924f8e [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 13:42:04 +00:00
Travis CI User
918e1cf183 [maven-release-plugin][skip ci] prepare release 17.160 2022-10-11 13:42:01 +00:00
Aleksandra Onych
59ab7e9458 ACS-3635 Alfresco WebDAV CSRF - allowInsecurePOSTMethod flag (#1488) 2022-10-11 15:05:48 +02:00
Tom Page
ccd421871c ACS-3651 Use Serializable for values in action parameters. 2022-10-11 12:00:17 +01:00
Travis CI User
fa1e616c72 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 10:40:52 +00:00
Travis CI User
5a34a2b01a [maven-release-plugin][skip ci] prepare release 17.159 2022-10-11 10:40:49 +00:00
Piotr Żurek
aae87ebffd PRODSEC-6550 Fix CSRF in the WebScript console Refresh Scripts form (#1483) 2022-10-11 12:05:35 +02:00
rrajoria
679746c907 Handle XSS 2022-10-11 13:01:09 +05:30
Travis CI User
44947e3d06 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-11 06:22:01 +00:00
Travis CI User
a94e660047 [maven-release-plugin][skip ci] prepare release 17.158 2022-10-11 06:21:59 +00:00
Marcin Strankowski
561d7d2f5a Update transform-core to 3.0.0-A4, transform-service to 2.0.0-A4, remove different version for jackson-databind. Update jackson version to 2.14.0-rc1 (#1484) 2022-10-11 08:44:52 +03:00
Travis CI User
78e69353d4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 19:29:30 +00:00
Travis CI User
71a88870bd [maven-release-plugin][skip ci] prepare release 17.157 2022-10-10 19:29:27 +00:00
George Evangelopoulos
6bcf33d672 ACS-3616: fix exception type for missing node id (#1457)
* ACS-3616: fix exception type for missing node id

* ACS-3616: fix exception handling for missing node id

* ACS-3616: update javadoc, add a constructor for the exception
2022-10-10 21:52:19 +03:00
Travis CI User
81f2bd7018 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 16:08:17 +00:00
Travis CI User
b3968bcd9e [maven-release-plugin][skip ci] prepare release 17.156 2022-10-10 16:08:14 +00:00
Maciej Pichura
307eaff896 ACS-3649, ACS-3650 Action validation mechanism + validations against Action Definitions (#1481)
* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint fixes.

* ACS-3572: Cleanup after removal of GET all Action constraints.

* ACS-3572: Fixing formatting in tests.

* ACS-3572: Loosening V1 constraints restrictions for aspects, types and properties.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3572: Adding validation for extra paramater.

* ACS-3649: Small refactors and fixes.

* ACS-3649: Validations against action definition.

* ACS-3649: Adding @Experimental annotation.

* ACS-3649: Fixes/refactoring after code review.

* ACS-3649: Removing ignored test
2022-10-10 17:13:51 +02:00
Travis CI User
0cfedbc979 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-10 09:13:35 +00:00
Travis CI User
89522ba09d [maven-release-plugin][skip ci] prepare release 17.155 2022-10-10 09:13:32 +00:00
Tom Page
86761bd408 Merge pull request #1478 from Alfresco/feature/ACS-3615_AllowNullParams
ACS-3615 Allow actions in rules without any params.
2022-10-10 09:29:29 +01:00
Maciej Pichura
4d6b4c2ecf ACS-3572 V1 API for action constraints (#1469)
* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint + logic + unit tests.

* ACS-3572: Action constraints endpoint fixes.

* ACS-3572: Cleanup after removal of GET all Action constraints.

* ACS-3572: Fixing formatting in tests.

* ACS-3572: Loosening V1 constraints restrictions for aspects, types and properties.

* ACS-3572: Removing unnecessary code.

* ACS-3572: Removing unnecessary field.

* ACS-3572: Removing unnecessary field - fixing the tests.

* ACS-3572: Renaming the endpoint and fixing license headers.

* ACS-3572: Fixing license headers.

* ACS-3572: Fixing tas-restapi dependency version.

* ACS-3649: Bumping tes-restapi version.

* ACS-3649: Bumping tes-restapi version.
2022-10-10 10:14:47 +02:00
Travis CI User
98cb7762c4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-09 09:44:47 +00:00
Travis CI User
ee01595f31 [maven-release-plugin][skip ci] prepare release 17.154 2022-10-09 09:44:44 +00:00
Elia Porciani
75acf5110e Fix/acs 2699 mandatory modifier (#1472)
[ACS-2699] managed + and - modifiers in fts query parser
2022-10-09 10:47:18 +02:00
Travis CI User
3a5971e267 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-09 00:11:41 +00:00
Travis CI User
99ef570054 [maven-release-plugin][skip ci] prepare release 17.153 2022-10-09 00:11:39 +00:00
Alfresco CI User
9649324d33 [force] Force release for 2022-10-09. 2022-10-09 00:04:36 +00:00
Tom Page
ad96f85251 ACS-3615 Allow actions in rules without any params. 2022-10-07 16:37:08 +01:00
krdabrowski
7ac48f8a99 ACS-3687: Execute rules API: Remove field "isEachInheritedRuleExecuted" (#1476)
* ACS-3620: E2Es - API for manual triggering rules on a folder
2022-10-07 17:01:08 +02:00
Travis CI User
aa38bcf9df [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-07 14:27:33 +00:00
Travis CI User
86d1d36ffe [maven-release-plugin][skip ci] prepare release 17.152 2022-10-07 14:27:31 +00:00
krdabrowski
b557a0d0f1 ACS-3620: E2Es - API for manual triggering rules on a folder (#1471) 2022-10-07 15:51:48 +02:00
Tom Page
1f81a50677 Merge pull request #1474 from Alfresco/feature/ACS-3657_PartialListOfRuleSets
ACS-3657 Allow returning partial list of rule sets.
2022-10-07 14:38:39 +01:00
Tom Page
855e2522f2 ACS-3657 Allow returning partial list of rule sets.
If a user does not have access to a rule set applied to a node then it will be
excluded from the results, but the user will be able to see the list of other
rule sets.

Also add E2E tests for permissions when viewing rule sets.
2022-10-07 13:03:37 +01:00
Travis CI User
f342b27c74 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-07 11:29:09 +00:00
Travis CI User
b00f01d385 [maven-release-plugin][skip ci] prepare release 17.151 2022-10-07 11:29:06 +00:00
rrajoria
ce68c4bf8b Reverting Change 2022-10-07 15:58:52 +05:30
Travis CI User
2544885f5e [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-05 17:02:40 +00:00
Travis CI User
1f7b272e57 [maven-release-plugin][skip ci] prepare release 17.150 2022-10-05 17:02:37 +00:00
Tom Page
df92ff9328 Merge pull request #1466 from Alfresco/feature/ACS-3630_PrivateActionTests
ACS-3630 E2E tests for creating and updating rules with private actions.
2022-10-05 16:24:47 +01:00
Travis CI User
b262c8fb92 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-05 15:19:28 +00:00
Travis CI User
0254323de5 [maven-release-plugin][skip ci] prepare release 17.149 2022-10-05 15:19:26 +00:00
Tom Page
89e8f7ff66 Merge master into ACS-3630_PrivateActionTests. 2022-10-05 16:09:29 +01:00
Tom Page
5735a41a40 Merge pull request #1468 from Alfresco/feature/ACS-3291_LinkUnlinkPermissionChecks
ACS-3291 Permission checks when linking and unlinking to rule sets.
2022-10-05 15:37:25 +01:00
Piotr Żurek
68b9a0e8a6 ACS-3643 Add meaningful message in the Workflow Console when deployment fails (#1467) 2022-10-05 15:53:42 +02:00
Tom Page
39f4a2179e ACS-3630 Use existing features in AccessRestrictionUtil. 2022-10-05 14:33:18 +01:00
Tom Page
440f0568e3 ACS-3291 Permission checks when linking and unlinking to rule sets. 2022-10-05 14:22:37 +01:00
krdabrowski
67f7fff0b7 ACS-3525: API for manual triggering rules on a folder (#1458)
* ACS-3525: API for manual triggering rules on a folder
2022-10-05 12:19:49 +02:00
Tom Page
1a08480f22 ACS-3630 E2E tests for creating and updating rules with private actions.
Ensure that 403 Forbidden is returned rather than 500 Internal Server Error.
2022-10-05 09:13:01 +01:00
Tom Page
8afd06a57f Merge pull request #1465 from Alfresco/feature/ACS-3605_LimitLinkedToBy
ACS-3605 Add limit to maximum size of optional linkedToBy field.
2022-10-05 09:05:21 +01:00
Tom Page
5e82555269 ACS-3605 Fix reference in unit test. 2022-10-04 16:21:23 +01:00
Tom Page
3682ddf652 ACS-3605 Add limit to maximum size of optional linkedToBy field. 2022-10-04 15:54:31 +01:00
Travis CI User
6747e300af [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-04 08:53:26 +00:00
Travis CI User
4bb2f67a48 [maven-release-plugin][skip ci] prepare release 17.148 2022-10-04 08:53:23 +00:00
Tom Page
c5c6b45f17 Merge pull request #1462 from Alfresco/feature/ACS-3377_UpdateRuleOrder
ACS-3377 Update rule order.
2022-10-04 09:16:30 +01:00
Travis CI User
1d9823d2e9 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-03 22:54:33 +00:00
Travis CI User
bfae9dd78d [maven-release-plugin][skip ci] prepare release 17.147 2022-10-03 22:54:30 +00:00
Kristian Dimitrov
86af67a435 ACS-3601: Add unlink e2es (#1461)
* ACS-3601: Add unlink e2es
2022-10-03 23:16:59 +01:00
Travis CI User
7ce6c121ef [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-03 16:00:31 +00:00
Travis CI User
d0061fb530 [maven-release-plugin][skip ci] prepare release 17.146 2022-10-03 16:00:28 +00:00
Tom Page
1c91452ee9 Merge pull request #1456 from Alfresco/feature/ACS-3376_GETRuleIds
ACS-3376 GET rule order within rule set.
2022-10-03 16:24:39 +01:00
Tom Page
f707906943 ACS-3377 Fix review comments. 2022-10-03 15:40:52 +01:00
Tom Page
af7e9f97aa ACS-3376 Simplify method of obtaining rule ids. 2022-10-03 15:28:00 +01:00
Tom Page
e9105f0f0c ACS-3377 Update rule order. 2022-10-03 10:04:07 +01:00
Travis CI User
282186b877 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-03 09:02:38 +00:00
Travis CI User
5ab44f4f35 [maven-release-plugin][skip ci] prepare release 17.145 2022-10-03 09:02:36 +00:00
kavitshah-gl
bf855c5965 Feature/acs-3579 (#1443)
* Fixed DeleteRecordTests-destroyOfRecord

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]
2022-10-03 13:47:59 +05:30
Travis CI User
d02f88eed4 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-02 00:13:36 +00:00
Travis CI User
e487061e96 [maven-release-plugin][skip ci] prepare release 17.144 2022-10-02 00:13:33 +00:00
Alfresco CI User
615406d5a1 [force] Force release for 2022-10-02. 2022-10-02 00:06:17 +00:00
Travis CI User
548fc9e64a [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-30 12:40:26 +00:00
Travis CI User
e7cc9ba008 [maven-release-plugin][skip ci] prepare release 17.143 2022-09-30 12:40:23 +00:00
kavitshah-gl
e10e9fe1c5 Update pom.xml
Updated Google Drive Version.
2022-09-30 16:42:10 +05:30
Travis CI User
d5a33e3f03 [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-30 09:54:34 +00:00
Travis CI User
b62dfc1d76 [maven-release-plugin][skip ci] prepare release 17.142 2022-09-30 09:54:32 +00:00
Sara
3711be4e80 Feature/acs 3623 descriptor startup log (#1460)
* Pick up api-explorer 7.3.0-A1

* remove unused import

* ACS-3623 Add customembeddedworkflow to descriptor startup log
2022-09-30 09:33:36 +01:00
Travis CI User
33297757bf [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-29 15:52:20 +00:00
Travis CI User
5f9c8fc499 [maven-release-plugin][skip ci] prepare release 17.141 2022-09-29 15:52:16 +00:00
tiagosalvado10
119ff309ac [MNT-23241] Prevent duplicated default headers if key/value pair is already in the request, otherwise, header is added (#1454)
* [MNT-23241] Prevent duplicated default headers if key/value pair is already in the request, otherwise, header is added
2022-09-29 16:17:23 +01:00
Tom Page
a93dd27674 ACS-3376 GET rule order within rule set. 2022-09-29 15:21:35 +01:00
128 changed files with 6091 additions and 1002 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<build>

View File

@@ -292,7 +292,6 @@ public class DeleteRecordTests extends BaseRMRestTest
* </pre>
*/
@Test (description = "Destroying record doesn't delete the content for the associated copy")
@Ignore
@AlfrescoTest (jira = "MNT-20145")
public void destroyOfRecord()
{
@@ -320,8 +319,8 @@ public class DeleteRecordTests extends BaseRMRestTest
RecordCategoryChild recFolder = createFolder(recordCategory.getId(), getRandomName("recFolder"));
RecordBodyFile recordBodyFile = RecordBodyFile.builder().targetParentId(recFolder.getId()).build();
Record recordFiled = getRestAPIFactory().getRecordsAPI().fileRecord(recordBodyFile, testFile.getNodeRefWithoutVersion());
getRestAPIFactory().getRecordsAPI().completeRecord(recordFiled.getId());
assertStatusCode(CREATED);
completeRecord(recordFiled.getId());
assertStatusCode(OK);
STEP("Execute the disposition schedule steps.");
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getUsername(), recordFiled.getName(),

View File

@@ -53,7 +53,6 @@ import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -135,7 +134,6 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
* <p/> TestRail Test C775<p/>
**/
@Test
@Ignore
@AlfrescoTest(jira = "RM-1622")
public void dispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
STEP("Create record category");
@@ -202,7 +200,6 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
* When the record is linked to a folder with the same disposition schedule
* */
@Test
@Ignore
@AlfrescoTest (jira = "RM-3060")
public void sameDispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
@@ -366,7 +363,6 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
}
@Test
@Ignore
@AlfrescoTest(jira = "RM-1622")
public void sameLevelDispositionScheduleStepsPeriodsCalculation() throws Exception {
@@ -419,7 +415,6 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
}
@Test (dependsOnMethods = {"sameLevelDispositionScheduleStepsPeriodsCalculation" })
@Ignore
public void deleteLongestPeriodTestPrecondition() {
// Delete the RM site
getRestAPIFactory().getRMSiteAPI().deleteRMSite();

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -1,3 +1,3 @@
SOLR6_TAG=2.0.3
SOLR6_TAG=2.0.5
POSTGRES_TAG=14.4
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -5,7 +5,7 @@
# Version label
version.major=7
version.minor=3
version.revision=0
version.revision=1
version.label=
# Edition label

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<build>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -8,7 +8,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-amps</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -14,7 +14,7 @@ function main()
maxResults: (args.maxResults !== null) ? parseInt(args.maxResults, 10) : DEFAULT_MAX_RESULTS,
pageSize: (args.pageSize !== null) ? parseInt(args.pageSize, 10) : DEFAULT_PAGE_SIZE,
startIndex: (args.startIndex !== null) ? parseInt(args.startIndex, 10) : 0,
facetFields: encodeURIComponent(args.facetFields),
facetFields: args.facetFields !== null ? args.facetFields.replace( /(<([^>]+)>)/ig, '') : null,
filters: args.filters,
encodedFilters: args.encodedFilters,
spell: (args.spellcheck !== null) ? (args.spellcheck == "true") : false

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<dependencies>

View File

@@ -203,18 +203,7 @@ public abstract class AbstractHttpClient implements AlfrescoHttpClient
}
}
/*
* @see AlfrescoHttpClient#setOverrideDefaultHeaders(boolean)
*/
public void setOverrideDefaultHeaders(boolean override)
{
if (httpClient != null)
{
if (httpClient instanceof RequestHeadersHttpClient)
{
((RequestHeadersHttpClient) httpClient).setOverrideDefaultHeaders(override);
}
}
}
}

View File

@@ -27,13 +27,4 @@ public interface AlfrescoHttpClient
*
*/
public void close();
/**
* Allows to override (or not) the default headers that will be included in HTTP requests
*
* @param override
* if true, it will prevent the default headers to be duplicated, otherwise the request may contain
* multiple instances of the same header
*/
public void setOverrideDefaultHeaders(boolean override);
}

View File

@@ -37,8 +37,6 @@ public class RequestHeadersHttpClient extends HttpClient
{
private Map<String, String> defaultHeaders;
private boolean overrideDefaultHeaders = false;
public RequestHeadersHttpClient(MultiThreadedHttpConnectionManager connectionManager)
{
@@ -60,11 +58,9 @@ public class RequestHeadersHttpClient extends HttpClient
if (defaultHeaders != null)
{
defaultHeaders.forEach((k,v) -> {
if (overrideDefaultHeaders)
{
method.setRequestHeader(k, v);
}
else
Header h = method.getRequestHeader(k);
boolean add = h == null || h.getValue() == null || !h.getValue().equals(v);
if (add)
{
method.addRequestHeader(k, v);
}
@@ -94,8 +90,4 @@ public class RequestHeadersHttpClient extends HttpClient
return super.executeMethod(hostconfig, method, state);
}
public void setOverrideDefaultHeaders(boolean overrideDefaultHeaders)
{
this.overrideDefaultHeaders = overrideDefaultHeaders;
}
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<dependencies>

View File

@@ -9,6 +9,6 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
</project>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -1,3 +1,3 @@
SOLR6_TAG=2.0.3
SOLR6_TAG=2.0.5
POSTGRES_TAG=14.4
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<modules>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<organization>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -5,6 +5,7 @@ import java.lang.reflect.Method;
import org.alfresco.dataprep.WorkflowService;
import org.alfresco.rest.core.RestProperties;
import org.alfresco.rest.core.RestWrapper;
import org.alfresco.rest.rules.RulesTestsUtils;
import org.alfresco.utility.LogFactory;
import org.alfresco.utility.TasProperties;
import org.alfresco.utility.data.DataContent;
@@ -61,6 +62,9 @@ public abstract class RestTest extends AbstractTestNGSpringContextTests
@Autowired
protected WorkflowService workflow;
@Autowired
protected RulesTestsUtils rulesUtils;
protected SiteModel testSite;
@BeforeSuite(alwaysRun = true)

View File

@@ -2,10 +2,13 @@ package org.alfresco.rest.actions;
import static org.testng.Assert.assertFalse;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import com.google.common.collect.ImmutableMap;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionConstraintDataModel;
import org.alfresco.rest.model.RestActionConstraintModel;
import org.alfresco.rest.model.RestActionDefinitionModel;
import org.alfresco.rest.model.RestActionDefinitionModelsCollection;
import org.alfresco.rest.model.RestNodeModel;
@@ -148,4 +151,66 @@ public class ActionsTests extends RestTest
restActionDefinition.getDescription().equals("This will add an aspect to the matched item.");
restActionDefinition.getTitle().equals("Add aspect");
}
@TestRail(section = {TestGroup.REST_API, TestGroup.ACTIONS}, executionType = ExecutionType.SANITY,
description = "Sanity test for ACTIONS endpoint GET action-conditions/{actionConstraintName}")
@Test(groups = {TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY})
public void testGetSingleActionConstraint()
{
final UserModel testUser = dataUser.createRandomTestUser();
restClient.authenticateUser(testUser);
final String compareOperationsName = "ac-compare-operations";
final RestActionConstraintModel actionConstraintCompareOperations =
restClient.withCoreAPI().usingActions().getActionConstraintByName(compareOperationsName);
restClient.assertStatusCodeIs(HttpStatus.OK);
final RestActionConstraintModel expectedComparatorConstraints = new RestActionConstraintModel();
expectedComparatorConstraints.setConstraintName(compareOperationsName);
expectedComparatorConstraints.setConstraintValues(getComparatorConstraints());
actionConstraintCompareOperations.assertThat().isEqualTo(expectedComparatorConstraints);
}
@TestRail(section = {TestGroup.REST_API, TestGroup.ACTIONS}, executionType = ExecutionType.SANITY,
description = "Sanity test for ACTIONS endpoint GET action-conditions/{actionConstraintName} - non existing constraint name")
@Test(groups = {TestGroup.REST_API, TestGroup.ACTIONS, TestGroup.SANITY})
public void testGetSingleNonExistingActionConstraint()
{
final UserModel testUser = dataUser.createRandomTestUser();
restClient.authenticateUser(testUser);
restClient.withCoreAPI().usingActions().getActionConstraintByName("dummy-name");
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND);
}
private List<RestActionConstraintDataModel> getComparatorConstraints()
{
final RestActionConstraintDataModel equalsConstraint = new RestActionConstraintDataModel();
equalsConstraint.setValue("EQUALS");
equalsConstraint.setLabel("Equals");
final RestActionConstraintDataModel containsConstraint = new RestActionConstraintDataModel();
containsConstraint.setValue("CONTAINS");
containsConstraint.setLabel("Contains");
final RestActionConstraintDataModel beginsConstraint = new RestActionConstraintDataModel();
beginsConstraint.setValue("BEGINS");
beginsConstraint.setLabel("Begins With");
final RestActionConstraintDataModel endsConstraint = new RestActionConstraintDataModel();
endsConstraint.setValue("ENDS");
endsConstraint.setLabel("Ends With");
final RestActionConstraintDataModel greaterThanConstraint = new RestActionConstraintDataModel();
greaterThanConstraint.setValue("GREATER_THAN");
greaterThanConstraint.setLabel("Greater Than");
final RestActionConstraintDataModel greaterThanEqualConstraint = new RestActionConstraintDataModel();
greaterThanEqualConstraint.setValue("GREATER_THAN_EQUAL");
greaterThanEqualConstraint.setLabel("Greater Than Or Equal To");
final RestActionConstraintDataModel lessThanConstraint = new RestActionConstraintDataModel();
lessThanConstraint.setValue("LESS_THAN");
lessThanConstraint.setLabel("Less Than");
final RestActionConstraintDataModel lessThanEqualConstraint = new RestActionConstraintDataModel();
lessThanEqualConstraint.setValue("LESS_THAN_EQUAL");
lessThanEqualConstraint.setLabel("Less Than Or Equal To");
return List.of(equalsConstraint, containsConstraint, beginsConstraint, endsConstraint, greaterThanConstraint,
greaterThanEqualConstraint, lessThanConstraint, lessThanEqualConstraint);
}
}

View File

@@ -1,15 +1,17 @@
package org.alfresco.rest.actions.access;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import org.alfresco.rest.actions.access.pojo.Action;
import org.alfresco.rest.actions.access.pojo.ActionCondition;
import org.alfresco.rest.actions.access.pojo.Rule;
import org.alfresco.utility.model.UserModel;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AccessRestrictionUtil {
public static final String MAIL_ACTION = "mail";
@@ -19,8 +21,8 @@ public class AccessRestrictionUtil {
"Only admin or system user is allowed to define uses of or directly execute this action";
private static final String ERROR_MESSAGE_FAILED_TO_SEND_EMAIL = "Failed to send email to:";
public static Map<String, String> createMailParameters(UserModel sender, UserModel recipient) {
Map<String, String> parameterValues = new HashMap<>();
public static Map<String, Serializable> createMailParameters(UserModel sender, UserModel recipient) {
Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put("from", sender.getEmailAddress());
parameterValues.put("to", recipient.getEmailAddress());
parameterValues.put("subject", "Test");
@@ -29,7 +31,7 @@ public class AccessRestrictionUtil {
return parameterValues;
}
public static Rule createRuleWithAction(String actionName, Map<String, String> parameterValues) {
public static Rule createRuleWithAction(String actionName, Map<String, Serializable> parameterValues) {
Rule rule = new Rule();
rule.setId("");
rule.setTitle("Test rule title");
@@ -57,7 +59,7 @@ public class AccessRestrictionUtil {
return rule;
}
public static Action createActionWithParameters(String actionName, Map<String, String> parameterValues) {
public static Action createActionWithParameters(String actionName, Map<String, Serializable> parameterValues) {
Action compositeAction = new Action();
compositeAction.setActionDefinitionName("composite-action");
@@ -76,7 +78,7 @@ public class AccessRestrictionUtil {
}
public static Action createAction(String actionName, Map<String, String> parameterValues) {
public static Action createAction(String actionName, Map<String, Serializable> parameterValues) {
Action action = new Action();
action.setActionDefinitionName(actionName);
action.setParameterValues(parameterValues);

View File

@@ -1,5 +1,15 @@
package org.alfresco.rest.actions.access;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_FIELD;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.getExpectedEmailSendFailureMessage;
import static org.hamcrest.Matchers.containsString;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.core.RestRequest;
import org.alfresco.rest.core.RestResponse;
@@ -13,15 +23,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.Map;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_FIELD;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.getExpectedEmailSendFailureMessage;
import static org.hamcrest.Matchers.containsString;
public class FormProcAdminAccessRestrictionTest extends RestTest {
private static final String ACTION_FORM_PROCESSOR_ENDPOINT = "alfresco/service/api/action/%s/formprocessor";
@@ -75,7 +76,7 @@ public class FormProcAdminAccessRestrictionTest extends RestTest {
.assertThat().body(ERROR_MESSAGE_FIELD, containsString(getExpectedEmailSendFailureMessage(testUser)));
}
private String generateBody(Map<String, String> mailParameters) {
private String generateBody(Map<String, Serializable> mailParameters) {
JSONObject json = new JSONObject();
mailParameters.forEach((key, value) -> json.put(PROPERTY_PREFIX + key, value));

View File

@@ -1,21 +1,20 @@
package org.alfresco.rest.actions.access;
import org.alfresco.rest.RestTest;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.alfresco.rest.core.RestWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.core.RestWrapper;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class V1AdminAccessRestrictionTest extends RestTest {
private UserModel adminUser;
@@ -45,7 +44,7 @@ public class V1AdminAccessRestrictionTest extends RestTest {
.executeAction(MAIL_ACTION, testFolder, createMailParameters(adminUser, testUser));
restClient.onResponse()
.assertThat().statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
.assertThat().statusCode(HttpStatus.FORBIDDEN.value())
.assertThat().body("entry.id", nullValue());
restClient.assertLastError().containsSummary(ERROR_MESSAGE_ACCESS_RESTRICTED);
}

View File

@@ -1,5 +1,6 @@
package org.alfresco.rest.actions.access.pojo;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@@ -8,7 +9,7 @@ public class Action {
private String actionedUponNode;
private List<ActionCondition> conditions;
private List<Action> actions;
private Map<String, String> parameterValues;
private Map<String, Serializable> parameterValues;
private boolean executeAsynchronously;
@@ -47,11 +48,11 @@ public class Action {
this.actions = actions;
}
public Map<String, String> getParameterValues() {
public Map<String, Serializable> getParameterValues() {
return parameterValues;
}
public void setParameterValues(Map<String, String> parameterValues) {
public void setParameterValues(Map<String, Serializable> parameterValues) {
this.parameterValues = parameterValues;
}
}

View File

@@ -27,13 +27,24 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.*;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.CHECKIN_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.COPY_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.ID;
import static org.alfresco.rest.rules.RulesTestsUtils.INVERTED;
import static org.alfresco.rest.rules.RulesTestsUtils.IS_SHARED;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_NAME_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_SCRIPT_PARAM_ID;
import static org.alfresco.rest.rules.RulesTestsUtils.SCRIPT_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.TEMPLATE_PARAM;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.constants.UserRole.SiteConsumer;
import static org.alfresco.utility.constants.UserRole.SiteContributor;
import static org.alfresco.utility.constants.UserRole.SiteManager;
import static org.alfresco.utility.model.FileModel.getRandomFileModel;
import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
import static org.alfresco.utility.model.UserModel.getRandomUserModel;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertEquals;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
@@ -42,22 +53,29 @@ import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import javax.json.Json;
import javax.json.JsonObject;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestActionConstraintModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleModelsCollection;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.ContentModel;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -87,12 +105,12 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRule()
{
RestRuleModel ruleModel = createRuleModelWithModifiedValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithModifiedValues();
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithModifiedValues();
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED)
.assertThat().field(ID).isNotNull()
@@ -110,10 +128,10 @@ public class CreateRulesTests extends RestTest
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("fake-id was not found");
restClient.assertLastError().containsSummary("Folder with id fake-id was not found");
}
/** Check creating a rule in a non-existent rule set returns an error. */
@@ -124,19 +142,19 @@ public class CreateRulesTests extends RestTest
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingRuleSet("fake-id").createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingRuleSet("fake-id").createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("fake-id was not found");
restClient.assertLastError().containsSummary("Rule set with id fake-id was not found");
}
/** Try to create a rule without a name and check the error. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithEmptyName()
{
RestRuleModel ruleModel = createRuleModel("");
RestRuleModel ruleModel = rulesUtils.createRuleModel("");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Rule name is a mandatory parameter");
@@ -146,11 +164,11 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void duplicateRuleNameIsAcceptable()
{
RestRuleModel ruleModel = createRuleModel("duplicateRuleName");
RestRuleModel ruleModel = rulesUtils.createRuleModel("duplicateRuleName");
STEP("Create two identical rules");
RestRuleModel ruleA = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleB = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleA = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleB = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
// Check that the names are the same but the ids are different.
ruleA.assertThat().field("name").is(ruleB.getName());
@@ -158,6 +176,7 @@ public class CreateRulesTests extends RestTest
}
/** Check that a user without permission to view the folder cannot create a rule in it. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void requireReadPermissionToCreateRule()
{
STEP("Create a user and use them to create a private site containing a folder");
@@ -169,13 +188,14 @@ public class CreateRulesTests extends RestTest
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a Collaborator cannot create a rule in a private folder. */
/** Check that a Collaborator cannot create a rule in a folder in a private site. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void siteCollaboratorCannotCreateRule()
{
testRolePermissionsWith(SiteCollaborator);
@@ -185,6 +205,7 @@ public class CreateRulesTests extends RestTest
}
/** Check that a Contributor cannot create a rule in a private folder. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void siteContributorCannotCreateRule()
{
testRolePermissionsWith(SiteContributor);
@@ -193,7 +214,8 @@ public class CreateRulesTests extends RestTest
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a Consumer cannot create a rule in a private folder. */
/** Check that a Consumer cannot create a rule in a folder in a private site. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void siteConsumerCannotCreateRule()
{
testRolePermissionsWith(SiteConsumer);
@@ -202,7 +224,8 @@ public class CreateRulesTests extends RestTest
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a siteManager can create a rule in a private folder. */
/** Check that a siteManager can create a rule in a folder in a private site. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void siteManagerCanCreateRule()
{
testRolePermissionsWith(SiteManager)
@@ -221,7 +244,7 @@ public class CreateRulesTests extends RestTest
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(fileModel).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(fileModel).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("folder is expected");
@@ -233,9 +256,9 @@ public class CreateRulesTests extends RestTest
{
STEP("Create a list of rules in one POST request");
List<String> ruleNames = List.of("ruleA", "ruleB", "ruleC");
List<RestRuleModel> ruleModels = ruleNames.stream().map(RulesTestsUtils::createRuleModel).collect(toList());
List<RestRuleModel> ruleModels = ruleNames.stream().map(rulesUtils::createRuleModel).collect(toList());
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createListOfRules(ruleModels);
restClient.assertStatusCodeIs(CREATED);
@@ -252,13 +275,13 @@ public class CreateRulesTests extends RestTest
public void createRulesWithOneError()
{
STEP("Try to create a three rules but the middle one has an error.");
RestRuleModel ruleA = createRuleModel("ruleA");
RestRuleModel ruleB = createRuleModel("");
RestRuleModel ruleA = rulesUtils.createRuleModel("ruleA");
RestRuleModel ruleB = rulesUtils.createRuleModel("");
// Don't set a name for Rule B.
RestRuleModel ruleC = createRuleModel("ruleC");
RestRuleModel ruleC = rulesUtils.createRuleModel("ruleC");
List<RestRuleModel> ruleModels = List.of(ruleA, ruleB, ruleC);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createListOfRules(ruleModels);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createListOfRules(ruleModels);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Rule name is a mandatory parameter");
@@ -268,10 +291,10 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutDescription()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
@@ -284,10 +307,10 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutTriggers()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
@@ -300,10 +323,10 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutErrorScript()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
@@ -316,11 +339,11 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithSharedFlag()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setIsShared(true);
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
@@ -333,9 +356,9 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRuleAndIncludeFieldsInResponse()
{
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.createSingleRule(ruleModel);
@@ -343,7 +366,7 @@ public class CreateRulesTests extends RestTest
rule.assertThat().field("isShared").isNotNull();
}
public RestRuleModel testRolePermissionsWith(UserRole userRole)
private RestRuleModel testRolePermissionsWith(UserRole userRole)
{
STEP("Create a user and use them to create a private site containing a folder");
SiteModel privateSite = dataSite.usingUser(user).createPrivateRandomSite();
@@ -352,9 +375,115 @@ public class CreateRulesTests extends RestTest
STEP(String.format("Add a user with '%s' role in the private site's folder", userRole.toString()));
UserModel userWithRole = dataUser.createRandomTestUser();
dataUser.addUserToSite(userWithRole, privateSite, userRole);
RestRuleModel ruleModel = createRuleModel("testRule", List.of(createDefaultActionModel()));
RestRuleModel ruleModel = rulesUtils.createRuleModel("testRule", List.of(rulesUtils.createAddAudioAspectAction()));
return restClient.authenticateUser(userWithRole).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
return restClient.authenticateUser(userWithRole).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
}
/** Check that the folder's owner can create rules, even if it is in a private site they aren't a member of. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkOwnerCanCreateRule()
{
STEP("Use admin to create a private site.");
SiteModel privateSite = dataSite.usingUser(dataUser.getAdminUser()).createPrivateRandomSite();
STEP("Add the user to the site, let them create a folder and then evict them from the site again.");
dataUser.addUserToSite(user, privateSite, SiteManager);
FolderModel folder = dataContent.usingUser(user).usingSite(privateSite).createFolder();
dataUser.removeUserFromSite(user, privateSite);
STEP("Check the folder owner can create a rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/** Check that an administrator can create a rule in a private site even if they aren't a member. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkAdminCanCreateRule()
{
STEP("Use a user to create a private site with a folder.");
SiteModel privateSite = dataSite.usingUser(user).createPrivateRandomSite();
FolderModel folder = dataContent.usingUser(user).usingSite(privateSite).createFolder();
STEP("Check admin can create a rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/** Check that a coordinator can create rules in folders outside sites. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkCoordinatorCanCreateRule()
{
STEP("Create a folder in the user's file space.");
FolderModel folder = dataContent.usingUser(user).usingUserHome().createFolder();
STEP("Create another user as a coordinator for this folder.");
UserModel coordinator = dataUser.createRandomTestUser("Rules");
/*
Update folder node properties to add a coordinator
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "coordinator.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(coordinator.getUsername(), "Coordinator");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
STEP("Check the coordinator can create a rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(coordinator).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/** Check that an editor cannot create rules in folders outside sites. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkEditorCannotCreateRule()
{
STEP("Create a folder in the user's file space.");
FolderModel folder = dataContent.usingUser(user).usingUserHome().createFolder();
STEP("Create another user as a editor for this folder.");
UserModel editor = dataUser.createRandomTestUser();
/*
Update folder node properties to add an editor
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "editor.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(editor.getUsername(), "Editor");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
STEP("Check the editor can create a rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(editor).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/** Check that a collaborator cannot create rules in folders outside sites. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkCollaboratorCannotCreateRule()
{
STEP("Create a folder in the user's file space.");
FolderModel folder = dataContent.usingUser(user).usingUserHome().createFolder();
STEP("Create another user as a collaborator for this folder.");
UserModel collaborator = dataUser.createRandomTestUser();
/*
Update folder node properties to add a collaborator
{ "permissions": { "isInheritanceEnabled": true, "locallySet": { "authorityId": "collaborator.getUsername()",
"name": "Coordinator", "accessStatus":"ALLOWED" } } }
*/
String putBody = getAddPermissionsBody(collaborator.getUsername(), "Collaborator");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).updateNode(putBody);
STEP("Check the collaborator can create a rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(collaborator).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/**
@@ -365,11 +494,11 @@ public class CreateRulesTests extends RestTest
{
final UserModel admin = dataUser.getAdminUser();
final RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(createVariousActions());
final RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleWithVariousActions());
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
expectedRuleModel.setActions(createVariousActions().getActions());
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
expectedRuleModel.setActions(rulesUtils.createRuleWithVariousActions().getActions());
expectedRuleModel.setTriggers(List.of("inbound"));
restClient.assertStatusCodeIs(CREATED);
@@ -377,16 +506,94 @@ public class CreateRulesTests extends RestTest
.assertThat().field(IS_SHARED).isNull();
}
/**
* Check get an error when creating a rule with action with empty parameter value.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithEmptyActionParameterValueShouldFail()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel checkinAction = rulesUtils.createCustomActionModel(CHECKIN_ACTION, Map.of("description", ""));
ruleModel.setActions(List.of(checkinAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST).assertLastError().containsSummary("Action parameter should not have empty or null value");
}
/**
* Check can create a rule with action without any parameters when action definition states all of them are optional.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithoutParameterWhenTheyAreOptional()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel checkinAction = rulesUtils.createCustomActionModel(CHECKIN_ACTION, null);
ruleModel.setActions(List.of(checkinAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/** Check that a normal user cannot create rules that use private actions. */
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActions_userCannotUsePrivateAction()
{
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
restClient.assertStatusCodeIs(FORBIDDEN)
.assertLastError().containsSummary(ERROR_MESSAGE_ACCESS_RESTRICTED);
}
/** Check that an administrator can create rules that use private actions. */
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActions_adminCanUsePrivateAction()
{
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
restClient.assertStatusCodeIs(CREATED);
}
/**
* Check that an administrator can create rules with email (private) action with reference to an email template.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActions_adminCanUseMailActionWithTemplate()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel mailAction = new RestActionBodyExecTemplateModel();
mailAction.setActionDefinitionId(MAIL_ACTION);
final Map<String, Serializable> params = new HashMap<>();
final UserModel sender = getRandomUserModel();
final UserModel recipient = getRandomUserModel();
params.put("from", sender.getEmailAddress());
params.put("to", recipient.getEmailAddress());
params.put("subject", "Test");
final RestActionConstraintModel constraint = rulesUtils.getConstraintsForActionParam(user, MAIL_ACTION, TEMPLATE_PARAM);
String templateScriptRef = constraint.getConstraintValues().stream().findFirst().get().getValue();
params.put(TEMPLATE_PARAM, templateScriptRef);
mailAction.setParams(params);
ruleModel.setActions(List.of(mailAction));
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/**
* Check we get error when attempt to create a rule without any actions.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithoutActionsShouldFail()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setActions(null);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -399,18 +606,290 @@ public class CreateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithInvalidActionsShouldFail()
{
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = new RestActionBodyExecTemplateModel();
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final String actionDefinitionId = "invalid-definition-value";
invalidAction.setActionDefinitionId(actionDefinitionId);
invalidAction.setParams(Map.of("dummy-key", "dummy-value"));
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(actionDefinitionId, Map.of("dummy-key", "dummy-value"));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(String.format("Invalid rule action definition requested %s", actionDefinitionId));
}
/**
* Check we get error when attempt to create a rule with an action tha is not applicable to rules.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithNotApplicableActionShouldFail()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction =
rulesUtils.createCustomActionModel(RulesTestsUtils.DELETE_RENDITION_ACTION, Map.of("dummy-key", "dummy-value"));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(String.format("Invalid rule action definition requested %s", RulesTestsUtils.DELETE_RENDITION_ACTION));
}
/**
* Check we get error when attempt to create a rule with missing action parameters.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithMissingActionParametersShouldFail()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction =
rulesUtils.createCustomActionModel(RulesTestsUtils.COPY_ACTION, Collections.emptyMap());
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action parameters should not be null or empty for this action. See Action Definition for action of: %s",
COPY_ACTION));
}
/**
* Check we get error when attempt to create a rule with parameter not fulfilling constraint.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActionParameterNotFulfillingConstraint()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final String actionDefinitionId = SCRIPT_ACTION;
final String scriptRef = RULE_SCRIPT_PARAM_ID;
final String scriptNodeId = "dummy-script-node-id";
final RestActionBodyExecTemplateModel scriptAction = rulesUtils.createCustomActionModel(actionDefinitionId, Map.of(scriptRef, scriptNodeId));
ruleModel.setActions(List.of(scriptAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
final String acScriptsConstraint = "ac-scripts";
restClient.assertLastError().containsSummary(
String.format("Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s",
scriptRef, scriptNodeId, acScriptsConstraint));
}
/**
* Check we get error when attempt to create a rule with action parameter that should not be passed.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithInvalidActionParameterShouldFail()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final String invalidParameterKey = "invalidParameterKey";
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(
RulesTestsUtils.ADD_FEATURES_ACTION, Map.of(invalidParameterKey, "dummyValue"));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action of definition id: %s must not contain parameter of name: %s", RulesTestsUtils.ADD_FEATURES_ACTION, invalidParameterKey));
}
/**
* Check we get error when attempt to create a rule with missing mandatory action parameter.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithoutMandatoryActionParametersShouldFail()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(COPY_ACTION, Map.of("deep-copy",false));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Missing action's mandatory parameter: destination-folder");
}
/**
* Check we get error when attempting to create a rule that copies files to a non-existent folder.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleThatUsesNonExistentNode()
{
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(
COPY_ACTION, Map.of("destination-folder", "non-existent-node"));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary(actionDefinitionId);
restClient.assertLastError().containsSummary("The entity with id: non-existent-node was not found");
}
/**
* Check we get error when attempting to create a rule that references a folder that the user does not have read permission for.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleThatUsesNodeWithoutReadPermission()
{
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(
COPY_ACTION, Map.of("destination-folder", privateFolder.getNodeRef()));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary("The entity with id: " + privateFolder.getNodeRef() + " was not found");
}
/**
* Check we get error when attempting to create a rule that copies files to a folder that a user only has read permission for.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleThatWritesToNodeWithoutPermission()
{
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(
COPY_ACTION, Map.of("destination-folder", privateFolder.getNodeRef()));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("No proper permissions for node: " + privateFolder.getNodeRef());
}
/**
* Check we get error when attempting to create a rule that moves files to a node which is not a folder
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleThatMovesToNodeWhichIsNotAFolderShouldFail()
{
final FileModel fileModel = dataContent.usingUser(user).usingSite(site).createContent(getRandomFileModel(TEXT_PLAIN));
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel invalidAction = rulesUtils.createCustomActionModel(
RulesTestsUtils.MOVE_ACTION, Map.of("destination-folder", fileModel.getNodeRef()));
ruleModel.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Node is not a folder " + fileModel.getNodeRef());
}
/**
* Check we get error when attempting to create a rule with mail action defined with non-existing mail template.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithMailActionReferringToNonExistingTemplate()
{
final RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
final RestActionBodyExecTemplateModel mailAction = new RestActionBodyExecTemplateModel();
mailAction.setActionDefinitionId(MAIL_ACTION);
final Map<String, Serializable> params = new HashMap<>();
final UserModel sender = getRandomUserModel();
final UserModel recipient = getRandomUserModel();
params.put("from", sender.getEmailAddress());
params.put("to", recipient.getEmailAddress());
params.put("subject", "Test");
final String mailTemplate = "non-existing-node-id";
params.put(TEMPLATE_PARAM, mailTemplate);
mailAction.setParams(params);
ruleModel.setActions(List.of(mailAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Action parameter: template has invalid value (" + mailTemplate +
"). Look up possible values for constraint name ac-email-templates");
}
/**
* Check the user can create a rule with a script.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkCanUseScriptInRule()
{
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel scriptAction = rulesUtils.createCustomActionModel(
SCRIPT_ACTION, Map.of(RULE_SCRIPT_PARAM_ID, rulesUtils.getReviewAndApproveWorkflowNode()));
ruleModel.setActions(List.of(scriptAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
}
/**
* Check the script has to be stored in the scripts directory in the data dictionary.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkCantUseNodeOutsideScriptsDirectory()
{
STEP("Copy script to location outside data dictionary.");
FolderModel folderOutsideDataDictionary = dataContent.usingUser(user).usingSite(site).createFolder();
String sourceNodeId = rulesUtils.getReviewAndApproveWorkflowNode();
ContentModel sourceNode = new ContentModel("/Data Dictionary/Scripts/start-pooled-review-workflow.js");
sourceNode.setNodeRef("/workspace://SpacesStore/" + sourceNodeId);
CmisObject scriptOutsideDataDictionary = dataContent.getContentActions().copyTo(dataUser.getAdminUser().getUsername(),
dataUser.getAdminUser().getPassword(),
sourceNode.getCmisLocation(),
folderOutsideDataDictionary.getCmisLocation());
String scriptId = scriptOutsideDataDictionary.getId().substring(0, scriptOutsideDataDictionary.getId().indexOf(";"));
STEP("Try to use this script in rule.");
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel scriptAction = rulesUtils.createCustomActionModel(
SCRIPT_ACTION, Map.of(RULE_SCRIPT_PARAM_ID, scriptId));
ruleModel.setActions(List.of(scriptAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST)
.assertLastError().containsSummary("script-ref has invalid value");
}
/**
* Check a real category needs to be supplied when linking to a category.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void checkLinkToCategoryNeedsRealCategory()
{
STEP("Attempt to link to a category with a folder node, rather than a category node.");
String nonCategoryNodeRef = ruleFolder.getNodeRef();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
RestActionBodyExecTemplateModel categoryAction = rulesUtils.createCustomActionModel(
RulesTestsUtils.LINK_CATEGORY_ACTION, Map.of("category-value", nonCategoryNodeRef));
ruleModel.setActions(List.of(categoryAction));
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
}
/**
@@ -419,14 +898,14 @@ public class CreateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithConditions()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setConditions(createVariousConditions());
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(rulesUtils.createVariousConditions());
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
expectedRuleModel.setConditions(createVariousConditions());
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
expectedRuleModel.setConditions(rulesUtils.createVariousConditions());
expectedRuleModel.setTriggers(List.of("inbound"));
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED);
@@ -438,13 +917,13 @@ public class CreateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithConditions_emptyConditionList()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setConditions(createCompositeCondition(null));
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(rulesUtils.createCompositeCondition(null));
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
expectedRuleModel.setTriggers(List.of("inbound"));
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, ID, IS_SHARED);
@@ -458,17 +937,29 @@ public class CreateRulesTests extends RestTest
{
STEP("Try to create a rule with non existing category in conditions.");
String fakeCategoryId = "bdba5f9f-fake-id22-803b-349bcfd06fd1";
RestCompositeConditionDefinitionModel conditions = createCompositeCondition(List.of(
createCompositeCondition(!INVERTED, List.of(
createSimpleCondition("category", "equals", fakeCategoryId)
RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(List.of(
rulesUtils.createCompositeCondition(!INVERTED, List.of(
rulesUtils.createSimpleCondition("category", "equals", fakeCategoryId)
))
));
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(conditions);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Category in condition is invalid");
}
private String getAddPermissionsBody(String username, String role)
{
JsonObject userPermission = Json.createObjectBuilder().add("permissions",
Json.createObjectBuilder()
.add("isInheritanceEnabled", true)
.add("locallySet", Json.createObjectBuilder()
.add("authorityId", username)
.add("name", role).add("accessStatus", "ALLOWED")))
.build();
return userPermission.toString();
}
}

View File

@@ -27,7 +27,6 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.constants.UserRole.SiteContributor;
import static org.alfresco.utility.constants.UserRole.SiteManager;
@@ -83,20 +82,20 @@ public class DeleteRulesTests extends RestTest
final FolderModel ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
final List<RestRuleModel> createdRules = Stream.of("ruleA", "ruleB", "ruleC")
.map(ruleName -> {
RestRuleModel ruleModel = createRuleModel(ruleName);
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel(ruleName);
return restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
})
.collect(toList());
STEP("Attempt delete one rule");
final RestRuleModel ruleA = createdRules.get(0);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().deleteRule(ruleA.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().deleteRule(ruleA.getId());
restClient.assertStatusCodeIs(NO_CONTENT);
STEP("Get and check the rules from the folder after deleting one of them");
final RestRuleModelsCollection rulesAfterDeletion =
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().getListOfRules();
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(OK);
rulesAfterDeletion.assertThat().entriesListCountIs(createdRules.size() - 1);
Assert.assertTrue(rulesAfterDeletion.getEntries()
@@ -127,7 +126,7 @@ public class DeleteRulesTests extends RestTest
nonExistingFolder.setNodeRef(FAKE_NODE_REF);
STEP("Attempt delete the rule in non-existing folder");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistingFolder).usingDefaultRuleSet().deleteRule(testRule.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistingFolder).usingDefaultRuleSet().deleteRule(testRule.getId());
restClient.assertLastError().statusCodeIs(NOT_FOUND);
}
@@ -142,7 +141,7 @@ public class DeleteRulesTests extends RestTest
final RestRuleModel testRule = createRule(ruleFolder);
STEP("Attempt delete the rule in non-existing rule set");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingRuleSet(FAKE_NODE_REF).deleteRule(testRule.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingRuleSet(FAKE_NODE_REF).deleteRule(testRule.getId());
restClient.assertLastError().statusCodeIs(NOT_FOUND);
}
@@ -155,7 +154,7 @@ public class DeleteRulesTests extends RestTest
{
final FolderModel ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt delete non-existing rule");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().deleteRule(FAKE_NODE_REF);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().deleteRule(FAKE_NODE_REF);
restClient.assertLastError().statusCodeIs(NOT_FOUND);
}
@@ -173,7 +172,7 @@ public class DeleteRulesTests extends RestTest
final FolderModel anotherFolder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt delete an existing rule from a wrong but existing (second) folder");
restClient.authenticateUser(user).withCoreAPI().usingNode(anotherFolder).usingDefaultRuleSet().deleteRule(testRule.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(anotherFolder).usingDefaultRuleSet().deleteRule(testRule.getId());
restClient.assertLastError().statusCodeIs(NOT_FOUND);
}
@@ -187,13 +186,13 @@ public class DeleteRulesTests extends RestTest
final UserModel privateUser = dataUser.createRandomTestUser();
final SiteModel privateSite = dataSite.usingUser(privateUser).createPrivateRandomSite();
final FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
final RestRuleModel ruleModel = createRuleModel("Private site rule");
final RestRuleModel ruleModel = rulesUtils.createRuleModel("Private site rule");
final RestRuleModel createdRule =
restClient.authenticateUser(privateUser).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet()
restClient.authenticateUser(privateUser).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Try to delete the rule with another user");
restClient.authenticateUser(user).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().deleteRule(createdRule.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().deleteRule(createdRule.getId());
restClient.assertLastError().statusCodeIs(FORBIDDEN);
}
@@ -213,7 +212,7 @@ public class DeleteRulesTests extends RestTest
restClient.authenticateUser(user).withCoreAPI().usingSite(site).addPerson(siteCollaborator);
STEP("Check the manager can delete the rule");
restClient.authenticateUser(siteCollaborator).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(siteCollaborator).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.deleteRule(testRule.getId());
restClient.assertLastError().statusCodeIs(FORBIDDEN);
@@ -228,9 +227,9 @@ public class DeleteRulesTests extends RestTest
final UserModel privateUser = dataUser.createRandomTestUser();
final SiteModel privateSite = dataSite.usingUser(privateUser).createPrivateRandomSite();
final FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
final RestRuleModel ruleModel = createRuleModel("Private site rule");
final RestRuleModel ruleModel = rulesUtils.createRuleModel("Private site rule");
final RestRuleModel createdRule =
restClient.authenticateUser(privateUser).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet()
restClient.authenticateUser(privateUser).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Create a manager in the private site");
@@ -239,7 +238,7 @@ public class DeleteRulesTests extends RestTest
restClient.authenticateUser(privateUser).withCoreAPI().usingSite(privateSite).addPerson(siteManager);
STEP("Check the manager can delete the rule");
restClient.authenticateUser(siteManager).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet()
restClient.authenticateUser(siteManager).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.deleteRule(createdRule.getId());
restClient.assertStatusCodeIs(NO_CONTENT);
@@ -248,7 +247,7 @@ public class DeleteRulesTests extends RestTest
private RestRuleModel createRule(FolderModel ruleFolder)
{
STEP("Create a rule in the folder");
final RestRuleModel ruleModel = createRuleModel("Test rule");
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
final RestRuleModel ruleModel = rulesUtils.createRuleModel("Test rule");
return restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
}
}

View File

@@ -0,0 +1,298 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.AUDIO_ASPECT;
import static org.alfresco.rest.rules.RulesTestsUtils.LOCKABLE_ASPECT;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_NAME_DEFAULT;
import static org.alfresco.utility.report.log.Step.STEP;
import java.util.List;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestRuleExecutionModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests for POST /nodes/{nodeId}/rule-executions.
*/
@Test(groups = { TestGroup.RULES})
public class ExecuteRulesTests extends RestTest
{
private UserModel user;
private SiteModel site;
private FolderModel parentFolder;
private FolderModel childFolder;
private FileModel parentFolderFile;
private FileModel childFolderFile;
private RestRuleModel parentFolderRule;
private RestRuleModel childFolderRule;
@BeforeClass(alwaysRun = true)
public void dataPreparation()
{
STEP("Create user and a site");
user = dataUser.createRandomTestUser();
site = dataSite.usingUser(user).createPublicRandomSite();
}
@BeforeMethod(alwaysRun = true)
public void setUp()
{
STEP("Create parent folder, rule folder and file in it");
parentFolder = dataContent.usingUser(user).usingSite(site).createFolder();
childFolder = dataContent.usingUser(user).usingResource(parentFolder).createFolder();
parentFolderFile = dataContent.usingUser(user).usingResource(parentFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
childFolderFile = dataContent.usingUser(user).usingResource(childFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Create rules for parent and rule folders");
RestActionBodyExecTemplateModel addLockableAspectAction = rulesUtils.createAddAspectAction(LOCKABLE_ASPECT);
RestRuleModel ruleModel = rulesUtils.createRuleModel(RULE_NAME_DEFAULT, List.of(addLockableAspectAction));
ruleModel.setIsInheritable(true);
parentFolderRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
childFolderRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
}
/**
* Execute one rule with one action trying to add audio aspect to a file.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS, TestGroup.SANITY })
public void executeRules_onlyOwnedRules()
{
STEP("Check if file aspects don't contain Audio one");
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT);
STEP("Execute rule");
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if only Audio aspect was added");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).containsAspects(AUDIO_ASPECT);
}
/**
* Execute owned rule adding Audio aspect and inherited rule adding Lockable aspect.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS, TestGroup.SANITY })
public void executeRules_includeInheritedRules()
{
STEP("Check if file aspects don't contain Audio and Lockable ones");
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Execute rules including inherited rules");
RestRuleExecutionModel ruleExecutionRequest = rulesUtils.createRuleExecutionRequest();
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).executeRules(ruleExecutionRequest);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if Audio and Lockable aspects were added");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).containsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
}
/**
* Execute rules on parent folder (add Lockable aspect) including sub-folder folders (add Audio aspect).
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS, TestGroup.SANITY })
public void executeRules_includeSubFolderRules()
{
STEP("Check if parent folder's file aspects don't contain Audio and Lockable ones");
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Check if child folder's file aspects don't contain Audio and Lockable ones");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Execute rules on parent folder including sub-folders");
RestRuleExecutionModel ruleExecutionRequest = rulesUtils.createRuleExecutionRequest();
ruleExecutionRequest.setIsEachSubFolderIncluded(true);
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).executeRules(ruleExecutionRequest);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(true);
STEP("Check if Lockable aspects was added to parent folder's file");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode)
.containsAspects(LOCKABLE_ASPECT)
.notContainsAspects(AUDIO_ASPECT);
STEP("Check if Audio and Lockable aspects were added to child folder's file");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode)
.containsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
}
/**
* Try to execute disabled rule and check if nothing changed.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_disabledRule()
{
STEP("Disable child rules");
RestRuleModel updatedChildRule = rulesUtils.createRuleModelWithDefaultValues();
updatedChildRule.setIsEnabled(false);
restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).usingDefaultRuleSet().updateRule(childFolderRule.getId(), updatedChildRule);
STEP("Check if file aspects don't contain Audio one");
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT);
STEP("Execute rule");
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if Audio aspect is still missing");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT);
}
/**
* Try to execute inherited parent folder's rule which is not inheritable.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_notInheritableRule()
{
STEP("Set parent rule as not inheritable");
RestRuleModel updatedParentRule = rulesUtils.createRuleModelWithDefaultValues();
updatedParentRule.setIsInheritable(false);
restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet().updateRule(parentFolderRule.getId(), updatedParentRule);
STEP("Check if file aspects don't contain Audio and Lockable ones");
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT, LOCKABLE_ASPECT);
STEP("Execute child folder rules including inherited rules");
RestRuleExecutionModel executionResult = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
executionResult.assertThat().field("isEachSubFolderIncluded").is(false);
STEP("Check if Audio aspect is present and Lockable is still missing");
fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolderFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode)
.containsAspects(AUDIO_ASPECT)
.notContainsAspects(LOCKABLE_ASPECT);
}
/**
* Try to execute private folder's rules by user not added to site and receive 403.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_privateFolderResultsWith403()
{
STEP("Using admin create private site, folder and rule");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
dataContent.usingAdmin().usingResource(privateFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Try to execute private folder's rules by user");
restClient.authenticateUser(user).withPrivateAPI().usingNode(privateFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
}
/**
* Try to execute private folder's rules as site contributor and receive 403.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_privateFolderAsContributorResultsWith403()
{
STEP("Using admin create private site, folder, file in it, rule and add user to site as contributor");
UserModel contributor = dataUser.createRandomTestUser();
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
dataContent.usingAdmin().usingResource(privateFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
dataUser.usingAdmin().addUserToSite(contributor, privateSite, UserRole.SiteContributor);
STEP("Try to execute private folder's rules by contributor");
restClient.authenticateUser(contributor).withPrivateAPI().usingNode(privateFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN);
}
/**
* Execute private folder's rules as site collaborator.
*/
@Test(groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.ACTIONS })
public void executeRules_privateFolderAsCollaborator()
{
STEP("Using admin create private site, folder, file in it, rule and add user to site as collaborator");
UserModel collaborator = dataUser.createRandomTestUser();
UserModel admin = dataUser.getAdminUser();
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
FileModel privateFile = dataContent.usingAdmin().usingResource(privateFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
restClient.authenticateUser(admin).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
dataUser.usingAdmin().addUserToSite(collaborator, privateSite, UserRole.SiteCollaborator);
STEP("Check if file aspects don't contain Audio one");
RestNodeModel fileNode = restClient.authenticateUser(admin).withCoreAPI().usingNode(privateFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).notContainsAspects(AUDIO_ASPECT);
STEP("Execute private folder's rules by collaborator");
restClient.authenticateUser(collaborator).withPrivateAPI().usingNode(privateFolder).executeRules(rulesUtils.createRuleExecutionRequest());
restClient.assertStatusCodeIs(HttpStatus.CREATED);
STEP("Check if Audio aspect is present");
fileNode = restClient.authenticateUser(admin).withCoreAPI().usingNode(privateFile).getNode();
restClient.assertStatusCodeIs(HttpStatus.OK);
rulesUtils.assertThat(fileNode).containsAspects(AUDIO_ASPECT);
}
//TODO: add test(s) that would cover handling executing broken rule and/or broken rule execution (ACS-3699)
}

View File

@@ -25,7 +25,6 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.testng.Assert.assertEquals;
@@ -72,22 +71,22 @@ public class GetInheritedRulesTests extends RestTest
STEP("Create a parent and child folder, each with inheriting rules");
FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
RestRuleModel parentRule = createRuleModelWithModifiedValues();
parentRule = restClient.authenticateUser(user).withCoreAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
RestRuleModel childRule = createRuleModelWithModifiedValues();
childRule = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
RestRuleModel parentRule = rulesUtils.createRuleModelWithDefaultValues();
parentRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
RestRuleModel childRule = rulesUtils.createRuleModelWithDefaultValues();
childRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
STEP("Get the rules in the default rule set for the child folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
rules.assertThat().entriesListContains("id", childRule.getId())
.and().entriesListCountIs(1);
STEP("Get the rules in the inherited rule set for the child folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
String inheritedRuleSetId = ruleSets.getEntries().stream()
.filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
.findFirst().get().onModel().getId();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
.and().entriesListCountIs(1);
}
@@ -111,23 +110,23 @@ public class GetInheritedRulesTests extends RestTest
FolderModel folderB = dataContent.usingUser(user).usingResource(folderA).createFolder();
FolderModel folderC = dataContent.usingUser(user).usingResource(folderB).createFolder();
FolderModel folderD = dataContent.usingUser(user).usingResource(folderC).createFolder();
RestRuleModel ruleB = restClient.authenticateUser(user).withCoreAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleC = restClient.authenticateUser(user).withCoreAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleD = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleB = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
RestRuleModel ruleC = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
RestRuleModel ruleD = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Link folderA to ruleSetD");
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
linkModel.setId(folderD.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folderA).createRuleLink(linkModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folderA).createRuleLink(linkModel);
STEP("Get the rule sets for the folderD");
List<RestRuleSetModel> ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).getListOfRuleSets().getEntries();
List<RestRuleSetModel> ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).getListOfRuleSets().getEntries();
STEP("Check the rules for each rule set are as expected");
List<RestRuleModel> expectedRuleIds = List.of(ruleD, ruleB, ruleC);
IntStream.range(0, 2).forEach(index -> {
String ruleSetId = ruleSets.get(index).onModel().getId();
List<RestRuleModel> rules = restClient.authenticateUser(user)
.withCoreAPI()
.withPrivateAPI()
.usingNode(folderD)
.usingRuleSet(ruleSetId)
.getListOfRules()

View File

@@ -26,11 +26,10 @@
package org.alfresco.rest.rules;
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithDefaultValues;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
import static org.alfresco.rest.rules.RulesTestsUtils.MOVE_ACTION;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
@@ -45,6 +44,7 @@ import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.rest.model.RestRuleSetModelsCollection;
import org.alfresco.rest.model.RestRuleSettingsModel;
import org.alfresco.rest.requests.coreAPI.RestCoreAPI;
import org.alfresco.rest.requests.privateAPI.RestPrivateAPI;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
@@ -62,6 +62,8 @@ public class GetRuleSetsTests extends RestTest
private UserModel user;
private SiteModel site;
private FolderModel ruleFolder;
/** A folder with a rule in a private site owned by admin. */
private FolderModel privateFolder;
private FolderModel inheritingChildFolder;
private FolderModel notInheritingChildFolder;
private RestRuleModel rule;
@@ -80,19 +82,24 @@ public class GetRuleSetsTests extends RestTest
notInheritingChildFolder = dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
RestRuleSettingsModel doesntInherit = new RestRuleSettingsModel();
doesntInherit.setValue(false);
restClient.authenticateUser(user).withCoreAPI().usingNode(notInheritingChildFolder)
restClient.authenticateUser(user).withPrivateAPI().usingNode(notInheritingChildFolder)
.usingIsInheritanceEnabledRuleSetting().updateSetting(doesntInherit);
STEP("Create a rule in the folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
STEP("Use admin to create a private site containing a rule in a rule set that can be inherited.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
privateAPIForAdmin().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithModifiedValues());
}
/** Check we can get an empty list of rule sets. */
@@ -103,7 +110,7 @@ public class GetRuleSetsTests extends RestTest
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Get the rule sets for the folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder).getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
@@ -115,7 +122,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetsList()
{
STEP("Get the rule sets for the folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
@@ -131,16 +138,58 @@ public class GetRuleSetsTests extends RestTest
STEP("Try to load rule sets for a non-existent folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).getListOfRuleSets();
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).getListOfRuleSets();
restClient.assertStatusCodeIs(NOT_FOUND);
}
/** Check that we get a 403 error when trying to get rule sets for a folder we don't have read access to. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetsWithoutPermission()
{
STEP("Check a user cannot list rule sets without read access.");
privateAPIForUser().usingNode(privateFolder).getListOfRuleSets();
restClient.assertStatusCodeIs(FORBIDDEN);
}
/** Check that we can still list some rule sets if we don't have permission to view them all. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void permissionsAreRespectedWhenListingRuleSets()
{
STEP("Create a public site containing a parent and child folder with rule inheritance enabled.");
SiteModel publicSite = dataSite.usingUser(user).createPublicRandomSite();
FolderModel parentFolder = dataContent.usingUser(user).usingSite(publicSite).createFolder();
FolderModel childFolder = dataContent.usingUser(user).usingResource(parentFolder).createFolder();
RestRuleSettingsModel enabled = new RestRuleSettingsModel();
enabled.setValue(true);
privateAPIForUser().usingNode(parentFolder).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
STEP("Link the parent folder to a private rule set.");
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
linkModel.setId(privateFolder.getNodeRef());
privateAPIForAdmin().usingNode(parentFolder).createRuleLink(linkModel);
STEP("Create a rule on the child folder.");
privateAPIForUser().usingNode(childFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Check admin can view both rule sets.");
RestRuleSetModelsCollection adminViewOfRuleSets = privateAPIForAdmin().usingNode(childFolder).getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
RestRuleSetModel parentRuleSet = adminViewOfRuleSets.getEntries().get(0).onModel();
RestRuleSetModel childRuleSet = adminViewOfRuleSets.getEntries().get(1).onModel();
STEP("Check the normal user can only view the child rule set.");
RestRuleSetModelsCollection userViewOfRuleSets = privateAPIForUser().usingNode(childFolder).getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
userViewOfRuleSets.assertThat().entriesListContains("id", childRuleSet.getId())
.and().entriesListDoesNotContain("id", parentRuleSet.getId());
}
/** Check we can get the id of the folder that owns a list of rule sets. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetsAndOwningFolders()
{
STEP("Get the rule sets and owning folders");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(ruleFolder)
.include("owningFolder")
.getListOfRuleSets();
@@ -157,7 +206,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetsAndOwnedInclusionType()
{
STEP("Get the rule sets and inclusion type");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(ruleFolder)
.include("inclusionType")
.getListOfRuleSets();
@@ -174,7 +223,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetsAndInheritedInclusionType()
{
STEP("Get the rule sets and inclusion type");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(inheritingChildFolder)
.include("inclusionType")
.getListOfRuleSets();
@@ -191,7 +240,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetsWithoutInheriting()
{
STEP("Get the rule sets and inclusion type");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(notInheritingChildFolder)
.getListOfRuleSets();
@@ -204,7 +253,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetById()
{
STEP("Get the rule set using its rule set id");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getRuleSet(ruleSetId);
restClient.assertStatusCodeIs(OK);
@@ -222,7 +271,7 @@ public class GetRuleSetsTests extends RestTest
public void getDefaultRuleSetById()
{
STEP("Get the default rule set for the folder");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getDefaultRuleSet();
restClient.assertStatusCodeIs(OK);
@@ -236,7 +285,7 @@ public class GetRuleSetsTests extends RestTest
STEP("Try to load a rule set for a non-existent folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).getDefaultRuleSet();
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).getDefaultRuleSet();
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -246,7 +295,7 @@ public class GetRuleSetsTests extends RestTest
{
STEP("Get the rule set using fake rule set id");
String fakeRuleSetId = "fake-rule-set-id";
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).getRuleSet(fakeRuleSetId);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).getRuleSet(fakeRuleSetId);
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -255,7 +304,7 @@ public class GetRuleSetsTests extends RestTest
public void getRuleSetAndOwningFolder()
{
STEP("Get the rule set and owning folder");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI()
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(ruleFolder)
.include("owningFolder")
.getRuleSet(ruleSetId);
@@ -293,33 +342,33 @@ public class GetRuleSetsTests extends RestTest
dataContent.usingAdmin().usingResource(privateFolder).setInheritPermissions(false);
// Create the grandchild with user and use admin to move it under the private folder.
FolderModel publicGrandchild = dataContent.usingUser(user).usingSite(siteModel).createFolder();
coreAPIForAdmin().usingActions().executeAction("move", publicGrandchild, ImmutableMap.of("destination-folder", "workspace://SpacesStore/" + privateFolder.getNodeRef()));
coreAPIForAdmin().usingActions().executeAction(MOVE_ACTION, publicGrandchild, ImmutableMap.of("destination-folder", "workspace://SpacesStore/" + privateFolder.getNodeRef()));
// Create the non-inheriting folder.
FolderModel nonInheritingFolder = dataContent.usingUser(user).usingResource(folder).createFolder();
RestRuleSettingsModel nonInheriting = new RestRuleSettingsModel();
nonInheriting.setKey(IS_INHERITANCE_ENABLED);
nonInheriting.setValue(false);
coreAPIForUser().usingNode(nonInheritingFolder).usingIsInheritanceEnabledRuleSetting().updateSetting(nonInheriting);
privateAPIForUser().usingNode(nonInheritingFolder).usingIsInheritanceEnabledRuleSetting().updateSetting(nonInheriting);
// Create a child that will link to the rule and a child of that to inherit via the link.
FolderModel linkingFolder = dataContent.usingUser(user).usingResource(nonInheritingFolder).createFolder();
FolderModel descendantFolder = dataContent.usingUser(user).usingResource(linkingFolder).createFolder();
STEP("Create an inheritable rule in the folder and get the rule set id.");
RestRuleModel ruleModel = createRuleModelWithModifiedValues();
coreAPIForUser().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleSetModelsCollection ruleSets = coreAPIForUser().usingNode(folder).getListOfRuleSets();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithModifiedValues();
privateAPIForUser().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleSetModelsCollection ruleSets = privateAPIForUser().usingNode(folder).getListOfRuleSets();
String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
STEP("Create the link to the rule from the linking folder");
RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel();
ruleSetLink.setId(folder.getNodeRef());
coreAPIForUser().usingNode(linkingFolder).createRuleLink(ruleSetLink);
privateAPIForUser().usingNode(linkingFolder).createRuleLink(ruleSetLink);
STEP("Remove the user from the site");
dataUser.removeUserFromSite(user, siteModel);
STEP("Get the rule set and inheriting folders");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(folder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(folder)
.include("inheritedBy")
.getRuleSet(ruleSetId);
@@ -347,17 +396,17 @@ public class GetRuleSetsTests extends RestTest
dataUser.removeUserFromSite(user, siteModel);
STEP("Create a rule in the folder and link to it from the other two.");
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleSetModelsCollection ruleSets = coreAPIForAdmin().usingNode(ruleFolder).getListOfRuleSets();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleSetModelsCollection ruleSets = privateAPIForAdmin().usingNode(ruleFolder).getListOfRuleSets();
String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel();
ruleSetLink.setId(ruleFolder.getNodeRef());
coreAPIForUser().usingNode(publicFolder).createRuleLink(ruleSetLink);
coreAPIForAdmin().usingNode(privateFolder).createRuleLink(ruleSetLink);
privateAPIForUser().usingNode(publicFolder).createRuleLink(ruleSetLink);
privateAPIForAdmin().usingNode(privateFolder).createRuleLink(ruleSetLink);
STEP("Get the rule set and linkedToBy field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("linkedToBy")
.getRuleSet(ruleSetId);
@@ -377,14 +426,14 @@ public class GetRuleSetsTests extends RestTest
STEP("Create a folder with a rule set and a private child folder to inherit it");
FolderModel ruleFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Remove the user from the site");
dataUser.removeUserFromSite(user, siteModel);
STEP("Get the rule set and isInherited field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("isInherited", "inheritedBy")
.getDefaultRuleSet();
@@ -401,18 +450,18 @@ public class GetRuleSetsTests extends RestTest
STEP("Create a site and a folder with a rule");
SiteModel siteModel = dataSite.usingUser(user).createPublicRandomSite();
FolderModel ruleFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Create a second folder in the site that links to the rule set");
FolderModel secondFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
dataContent.usingUser(user).usingResource(secondFolder).createFolder();
RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel();
ruleSetLink.setId(ruleFolder.getNodeRef());
coreAPIForUser().usingNode(secondFolder).createRuleLink(ruleSetLink);
privateAPIForUser().usingNode(secondFolder).createRuleLink(ruleSetLink);
STEP("Get the rule set and isInherited field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("isInherited")
.getDefaultRuleSet();
@@ -429,17 +478,17 @@ public class GetRuleSetsTests extends RestTest
STEP("Create a site and a folder with a rule");
SiteModel siteModel = dataSite.usingUser(user).createPublicRandomSite();
FolderModel ruleFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Create a second folder in the site that links to the rule set");
FolderModel secondFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
RestRuleSetLinkModel ruleSetLink = new RestRuleSetLinkModel();
ruleSetLink.setId(ruleFolder.getNodeRef());
coreAPIForUser().usingNode(secondFolder).createRuleLink(ruleSetLink);
privateAPIForUser().usingNode(secondFolder).createRuleLink(ruleSetLink);
STEP("Get the rule set and isInherited field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("isInherited")
.getDefaultRuleSet();
@@ -458,20 +507,20 @@ public class GetRuleSetsTests extends RestTest
STEP("Create a folder with a rule set");
FolderModel ruleFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Create a private folder linking to the rule set");
FolderModel linkingFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
linkModel.setId(ruleFolder.getNodeRef());
coreAPIForAdmin().usingNode(linkingFolder).createRuleLink(linkModel);
privateAPIForAdmin().usingNode(linkingFolder).createRuleLink(linkModel);
STEP("Remove the user from the site");
dataUser.removeUserFromSite(user, siteModel);
STEP("Get the rule set and isLinkedTo field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("isLinkedTo", "linkedToBy", "owningFolder")
.getDefaultRuleSet();
@@ -490,12 +539,12 @@ public class GetRuleSetsTests extends RestTest
STEP("Create a site, a folder with a rule and a child folder that inherits it");
SiteModel siteModel = dataSite.usingUser(user).createPublicRandomSite();
FolderModel ruleFolder = dataContent.usingUser(user).usingSite(siteModel).createFolder();
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
coreAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
privateAPIForUser().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
dataContent.usingUser(user).usingResource(ruleFolder).createFolder();
STEP("Get the rule set and isLinkedTo field");
RestRuleSetModel ruleSet = coreAPIForUser().usingNode(ruleFolder)
RestRuleSetModel ruleSet = privateAPIForUser().usingNode(ruleFolder)
.include("isLinkedTo")
.getDefaultRuleSet();
@@ -503,13 +552,50 @@ public class GetRuleSetsTests extends RestTest
ruleSet.assertThat().field("isLinkedTo").is(false);
}
private RestCoreAPI coreAPIForUser()
/** Check that we can only view a rule set if have read permission. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void permissionsChecksForFolderWithPrivateAndPublicRuleSets()
{
return restClient.authenticateUser(user).withCoreAPI();
STEP("Create a public site containing a parent and child folder with rule inheritance enabled.");
SiteModel publicSite = dataSite.usingUser(user).createPublicRandomSite();
FolderModel parentFolder = dataContent.usingUser(user).usingSite(publicSite).createFolder();
FolderModel childFolder = dataContent.usingUser(user).usingResource(parentFolder).createFolder();
RestRuleSettingsModel enabled = new RestRuleSettingsModel();
enabled.setValue(true);
privateAPIForUser().usingNode(parentFolder).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
STEP("Link the parent folder to a private rule set.");
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
linkModel.setId(privateFolder.getNodeRef());
privateAPIForAdmin().usingNode(parentFolder).createRuleLink(linkModel);
STEP("Create a rule on the child folder.");
privateAPIForUser().usingNode(childFolder).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Use the admin user to get both rule sets.");
RestRuleSetModelsCollection adminViewOfRuleSets = privateAPIForAdmin().usingNode(childFolder).getListOfRuleSets();
RestRuleSetModel parentRuleSet = adminViewOfRuleSets.getEntries().get(0).onModel();
RestRuleSetModel childRuleSet = adminViewOfRuleSets.getEntries().get(1).onModel();
STEP("Check the normal user can only view the child rule set.");
privateAPIForUser().usingNode(childFolder).getRuleSet(parentRuleSet.getId());
restClient.assertStatusCodeIs(FORBIDDEN);
privateAPIForUser().usingNode(childFolder).getRuleSet(childRuleSet.getId());
restClient.assertStatusCodeIs(OK);
}
private RestCoreAPI coreAPIForAdmin()
{
return restClient.authenticateUser(dataUser.getAdminUser()).withCoreAPI();
}
private RestPrivateAPI privateAPIForUser()
{
return restClient.authenticateUser(user).withPrivateAPI();
}
private RestPrivateAPI privateAPIForAdmin()
{
return restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI();
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -27,14 +27,13 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.*;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.CREATED;
import java.util.List;
import java.util.stream.IntStream;
@@ -76,8 +75,8 @@ public class GetRulesTests extends RestTest
STEP("Create rules in the folder");
createdRules = Stream.of("ruleA", "ruleB").map(ruleName -> {
RestRuleModel ruleModel = createRuleModel(ruleName);
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModel(ruleName);
return restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
}).collect(toList());
createdRuleA = createdRules.get(0);
}
@@ -90,7 +89,7 @@ public class GetRulesTests extends RestTest
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Get the rules that apply to the folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet().getListOfRules();
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(NOT_FOUND);
assertTrue("Expected no rules to be present.", rules.isEmpty());
@@ -105,7 +104,7 @@ public class GetRulesTests extends RestTest
public void getRulesList()
{
STEP("Get the rules that apply to the folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().getListOfRules();
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(OK);
rules.assertThat().entriesListCountIs(createdRules.size());
@@ -123,7 +122,7 @@ public class GetRulesTests extends RestTest
STEP("Try to load rules for a non-existent folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().getListOfRules();
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -134,7 +133,7 @@ public class GetRulesTests extends RestTest
STEP("Create a folder in existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Try to load rules for a non-existent rule set.");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingRuleSet("fake-id").getListOfRules();
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingRuleSet("fake-id").getListOfRules();
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -143,7 +142,7 @@ public class GetRulesTests extends RestTest
public void getRulesListWithIncludedFields()
{
STEP("Get the rules that apply to the folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.getListOfRules();
@@ -152,7 +151,7 @@ public class GetRulesTests extends RestTest
rules.getEntries().get(i).onModel()
.assertThat().field("isShared").isNotNull()
.assertThat().field("description").isNull()
.assertThat().field("isEnabled").is(false)
.assertThat().field("isEnabled").is(true)
.assertThat().field("isInheritable").is(false)
.assertThat().field("isAsynchronous").is(false)
.assertThat().field("errorScript").isNull()
@@ -169,7 +168,7 @@ public class GetRulesTests extends RestTest
public void getSingleRule()
{
STEP("Load a particular rule");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().getSingleRule(createdRuleA.getId());
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().getSingleRule(createdRuleA.getId());
restClient.assertStatusCodeIs(OK);
@@ -183,14 +182,14 @@ public class GetRulesTests extends RestTest
public void getRulesOtherFieldsModified()
{
STEP("Create a rule with all other fields default values modified");
RestRuleModel ruleModel = createRuleModelWithModifiedValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithModifiedValues();
ruleModel.setTriggers(List.of("update"));
UserModel admin = dataUser.getAdminUser();
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithModifiedValues();
expectedRuleModel.setTriggers(List.of("update"));
restClient.assertStatusCodeIs(CREATED);
@@ -205,13 +204,13 @@ public class GetRulesTests extends RestTest
public void getRulesDefaultFields()
{
STEP("Create a rule with all other fields default values");
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
RestRuleModel expectedRuleModel = rulesUtils.createRuleModelWithDefaultValues();
expectedRuleModel.setTriggers(List.of("inbound"));
restClient.assertStatusCodeIs(CREATED);
@@ -229,7 +228,7 @@ public class GetRulesTests extends RestTest
STEP("Try to load a rule from a non-existent folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().getSingleRule("fake-rule-id");
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).usingDefaultRuleSet().getSingleRule("fake-rule-id");
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -240,7 +239,7 @@ public class GetRulesTests extends RestTest
STEP("Create a folder in existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Try to load rules for a non-existent rule set.");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingRuleSet("fake-id").getSingleRule("fake-rule-id");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingRuleSet("fake-id").getSingleRule("fake-rule-id");
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -251,7 +250,7 @@ public class GetRulesTests extends RestTest
STEP("Create a folder in existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Try to load a rule for a wrong but existing folder.");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(createdRuleA.getId());
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(createdRuleA.getId());
restClient.assertStatusCodeIs(NOT_FOUND);
}
@@ -260,7 +259,7 @@ public class GetRulesTests extends RestTest
public void getSingleRuleWithIncludedFields()
{
STEP("Load a particular rule");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.getSingleRule(createdRuleA.getId());
@@ -276,10 +275,10 @@ public class GetRulesTests extends RestTest
FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("Private site rule");
restClient.authenticateUser(privateUser).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(privateUser).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Try to get the rule with another user");
restClient.authenticateUser(user).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().getListOfRules();
restClient.authenticateUser(user).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().getListOfRules();
restClient.assertLastError()
.statusCodeIs(FORBIDDEN)
@@ -293,8 +292,8 @@ public class GetRulesTests extends RestTest
UserModel privateUser = dataUser.createRandomTestUser();
SiteModel privateSite = dataSite.usingUser(privateUser).createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
RestRuleModel ruleModel = createRuleModel("Private site rule");
restClient.authenticateUser(privateUser).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
RestRuleModel ruleModel = rulesUtils.createRuleModel("Private site rule");
restClient.authenticateUser(privateUser).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
STEP("Create a collaborator in the private site");
UserModel collaborator = dataUser.createRandomTestUser();
@@ -302,7 +301,7 @@ public class GetRulesTests extends RestTest
restClient.authenticateUser(privateUser).withCoreAPI().usingSite(privateSite).addPerson(collaborator);
STEP("Check the collaborator can view the rule");
RestRuleModelsCollection rules = restClient.authenticateUser(collaborator).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().getListOfRules();
RestRuleModelsCollection rules = restClient.authenticateUser(collaborator).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(OK);
rules.assertThat().entriesListContains("name", "Private site rule");
@@ -315,20 +314,22 @@ public class GetRulesTests extends RestTest
public void getRuleActions()
{
STEP("Create a rule with a few actions");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
final RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(createVariousActions());
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
final RestRuleModel ruleWithVariousActions = rulesUtils.createRuleWithVariousActions();
final UserModel admin = dataUser.getAdminUser();
final RestRuleModel rule = restClient.authenticateUser(admin).withPrivateAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(ruleWithVariousActions);
STEP("Retrieve the created rule via the GET endpoint");
final RestRuleModel getRuleBody = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(rule.getId());
final RestRuleModel getRuleBody = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(rule.getId());
STEP("Assert that actions are returned as expected from the GET endpoint");
restClient.assertStatusCodeIs(OK);
getRuleBody.assertThat().field(ACTIONS).contains("actionDefinitionId=copy")
.assertThat().field(ACTIONS).contains("destination-folder=dummy-folder-node")
.assertThat().field(ACTIONS).contains("destination-folder=" + rulesUtils.getCopyDestinationFolder().getNodeRef())
.assertThat().field(ACTIONS).contains("deep-copy=true")
.assertThat().field(ACTIONS).contains("actionDefinitionId=check-out")
.assertThat().field(ACTIONS).contains("destination-folder=fake-folder-node")
.assertThat().field(ACTIONS).contains("destination-folder=" + rulesUtils.getCheckOutDestinationFolder().getNodeRef())
.assertThat().field(ACTIONS).contains("assoc-name=cm:checkout");
}
@@ -339,16 +340,16 @@ public class GetRulesTests extends RestTest
public void getRulesConditions()
{
STEP("Create a rule with several conditions");
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setConditions(createVariousConditions());
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
ruleModel.setConditions(rulesUtils.createVariousConditions());
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Retrieve the created rule via the GET endpoint");
final RestRuleModel getRuleBody = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(rule.getId());
final RestRuleModel getRuleBody = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().getSingleRule(rule.getId());
STEP("Assert that conditions are retrieved using the GET endpoint");
restClient.assertStatusCodeIs(OK);

View File

@@ -0,0 +1,203 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.OK;
import java.util.List;
import java.util.stream.IntStream;
import com.google.common.collect.Lists;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test (groups = { TestGroup.RULES })
public class ReorderRules extends RestTest
{
private UserModel user;
private SiteModel site;
@BeforeClass (alwaysRun = true)
public void dataPreparation()
{
STEP("Create a user and site.");
user = dataUser.createRandomTestUser();
site = dataSite.usingUser(user).createPublicRandomSite();
}
/** Check we can get the ordered list of rules in a rule set. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getOrderedRuleIds()
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Get the default rule set for the folder including the ordered rule ids");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").getDefaultRuleSet();
List<String> expectedRuleIds = rules.stream().map(RestRuleModel::getId).collect(toList());
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(expectedRuleIds);
}
/** Check that a user can view the order of the rules in a rule set if they only have read permission. */
@Test
public void getRuleSetAndRuleIdsWithReadOnlyPermission()
{
STEP("Create a site owned by admin and add user as a consumer");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteConsumer);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Get the rule set with the ordered list of rules");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").getDefaultRuleSet();
restClient.assertStatusCodeIs(OK);
List<String> ruleIds = rules.stream().map(RestRuleModel::getId).collect(toList());
ruleSet.assertThat().field("ruleIds").is(ruleIds);
}
/** Check we can reorder the rules in a rule set. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void reorderRules()
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Reverse the order of the rules within the rule set");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Check we can reorder the rules in a rule set by editing the response from the GET. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void reorderRulesUsingResponseFromGET()
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Get the rule set with its id.");
RestRuleSetModel ruleSetResponse = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").getDefaultRuleSet();
STEP("Reverse the order of the rules within the rule set");
ruleSetResponse.setRuleIds(Lists.reverse(ruleSetResponse.getRuleIds()));
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").updateRuleSet(ruleSetResponse);
restClient.assertStatusCodeIs(OK);
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Check that a user cannot reorder the rules in a rule set if they only have read permission. */
@Test
public void reorderRulesWithoutPermission()
{
STEP("Create a site owned by admin and add user as a consumer");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteContributor);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Try to reorder the rules as the contributor");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/** Check that a user can reorder the rules in a rule set if they have write permission. */
@Test
public void reorderRulesWithPermission()
{
STEP("Create a site owned by admin and add user as a collaborator");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteCollaborator);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Try to reorder the rules as the contributor");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Create three rules in the given folder. */
private List<RestRuleModel> createRulesInFolder(FolderModel folder, UserModel user)
{
return IntStream.range(0, 3).mapToObj(index ->
{
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
return restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
}).collect(toList());
}
}

View File

@@ -25,11 +25,14 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.SiteConsumer;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.NO_CONTENT;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
@@ -74,12 +77,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -87,7 +90,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a rule folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -96,7 +99,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -104,7 +107,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
@@ -127,12 +130,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -140,7 +143,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a rule set");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleSetId);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -149,7 +152,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -157,7 +160,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection likedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection likedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
@@ -169,7 +172,6 @@ public class RuleSetLinksTests extends RestTest
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we get 404 when linking to a non-existing rule set/folder.
*/
@@ -182,7 +184,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to non-existing rule set");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId("dummy-rule-set-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result is 404");
restClient.assertStatusCodeIs(NOT_FOUND);
@@ -201,7 +203,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a folder without rules");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(folder2.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -219,17 +221,17 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder2 = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create rules in both folders.");
RestRuleModel ruleModel1 = createRuleModel("ruleName1");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).usingDefaultRuleSet()
RestRuleModel ruleModel1 = rulesUtils.createRuleModel("ruleName1");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).usingDefaultRuleSet()
.createSingleRule(ruleModel1);
RestRuleModel ruleModel2 = createRuleModel("ruleName2");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder2).usingDefaultRuleSet()
RestRuleModel ruleModel2 = rulesUtils.createRuleModel("ruleName2");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder2).usingDefaultRuleSet()
.createSingleRule(ruleModel2);
STEP("Link from a folder with rules");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(folder2.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -250,7 +252,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a file node");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(fileContent.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -268,12 +270,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel childFolder = dataContent.usingUser(user).usingSite(site).usingResource(parentFolder).createFolder();
STEP("Create a rule in the parent folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -281,7 +283,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to the parent folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(parentFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -290,7 +292,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if child folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(childFolder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -298,7 +300,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if child folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(childFolder)
.include("inclusionType")
.getListOfRuleSets();
@@ -310,4 +312,191 @@ public class RuleSetLinksTests extends RestTest
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we get an error when trying to link to a rule set that we can't view.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void linkToRuleSetWithoutPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Use a normal user to try to link to the rule.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/**
* Check we are able to link to a rule set with only read permission.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void linkToRuleSetWithOnlyReadPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the normal user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use a normal user to try to link to the rule.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
}
/**
* Check we can DELETE/unlink a ruleset
*
* DELETE /nodes/{folderNodeId}/rule-set-links/{ruleSetId}.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void unlinkRuleSet()
{
STEP("Create folders in existing site");
final FolderModel ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
STEP("Link to a rule folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Unlink the rule set");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet(ruleSetId);
STEP("Assert unlink result");
restClient.assertStatusCodeIs(NO_CONTENT);
STEP("GET the rule set and isLinkedTo field.");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("isLinkedTo", "linkedToBy", "owningFolder")
.getDefaultRuleSet();
STEP("Assert linkedTo is false.");
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("isLinkedTo").is(false)
.assertThat().field("linkedToBy").isEmpty();
}
/**
* Check a 400 is thrown when using folder/content id instead of a ruleSetId.
*
* DELETE /nodes/{folderNodeId}/rule-set-links/{ruleSetId}
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void unlinkUsingDocumentId()
{
STEP("Create folders in existing site");
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt to unlink the rule set");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet(folder.getNodeRef());
STEP("Assert unlink result");
restClient.assertStatusCodeIs(BAD_REQUEST)
.assertLastError().containsSummary("NodeId of a rule set is expected!");
}
/**
* Check a 404 is thrown when using non-existent id instead of a ruleSetId.
*
* DELETE /nodes/{folderNodeId}/rule-set-links/{ruleSetId}
*/
//TODO This test may need to be modified once ACS-3616 is done
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void unlinkUsingRandomId()
{
STEP("Create folders in existing site");
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt to unlink the rule set");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet("non-existent-id");
STEP("Assert unlink result");
restClient.assertStatusCodeIs(NOT_FOUND)
.assertLastError().containsSummary("Rule set with id non-existent-id was not found");
}
/**
* Check we cannot unlink from a rule set that we can't view.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void unlinkFromRuleSetWithoutPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use the consumer to create a folder with a link to the private rule set.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
STEP("Remove the user from the private site.");
dataUser.usingAdmin().removeUserFromSite(user, privateSite);
STEP("Use the user to try to unlink from the rule set.");
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).unlinkRuleSet("-default-");
restClient.assertStatusCodeIs(FORBIDDEN);
}
/**
* Check we can unlink from a rule set if we only have read permission for it.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void unlinkFromRuleSetWithOnlyReadPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use the consumer to create a folder with a link to the private rule set.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
STEP("Use the consumer to try to unlink from the rule set.");
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).unlinkRuleSet("-default-");
restClient.assertStatusCodeIs(NO_CONTENT);
}
}

View File

@@ -25,16 +25,36 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.MAIL_ACTION;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.createMailParameters;
import static org.alfresco.utility.model.UserModel.getRandomUserModel;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.core.RestWrapper;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestActionConstraintDataModel;
import org.alfresco.rest.model.RestActionConstraintModel;
import org.alfresco.rest.model.RestActionDefinitionModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.model.RestParameterDefinitionModel;
import org.alfresco.rest.model.RestRuleExecutionModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestSimpleConditionDefinitionModel;
import org.alfresco.utility.data.DataContent;
import org.alfresco.utility.data.DataSite;
import org.alfresco.utility.data.DataUserAIS;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RulesTestsUtils
{
static final String RULE_NAME_DEFAULT = "ruleName";
@@ -43,7 +63,7 @@ public class RulesTestsUtils
static final boolean RULE_CASCADE_DEFAULT = true;
static final boolean RULE_ASYNC_DEFAULT = true;
static final boolean RULE_SHARED_DEFAULT = false;
static final String RULE_ERROR_SCRIPT_DEFAULT = "error-script";
static final String RULE_ERROR_SCRIPT_LABEL = "Start Pooled Review and Approve Workflow";
static final String INBOUND = "inbound";
static final String UPDATE = "update";
static final String OUTBOUND = "outbound";
@@ -52,48 +72,165 @@ public class RulesTestsUtils
static final String AND = "and";
static final String ID = "id";
static final String IS_SHARED = "isShared";
static final String AUDIO_ASPECT = "audio:audio";
static final String LOCKABLE_ASPECT = "cm:lockable";
static final String TEMPLATE_PARAM = "template";
static final String RULE_SCRIPT_PARAM_ID = "script-ref";
static final String CHECKIN_ACTION = "check-in";
static final String LINK_CATEGORY_ACTION = "link-category";
static final String DELETE_RENDITION_ACTION = "delete-rendition";
static final String COPY_ACTION = "copy";
static final String ADD_FEATURES_ACTION = "add-features";
static final String MOVE_ACTION = "move";
static final String SCRIPT_ACTION = "script";
@Autowired
private RestWrapper restClient;
@Autowired
private DataUserAIS dataUser;
@Autowired
private DataSite dataSite;
@Autowired
private DataContent dataContent;
/** Public site used by these helper methods. This is populated by the getter and should not be accessed directly. */
private SiteModel publicSite;
/** Script node used by these helper methods. This is populated by the getter and should not be accessed directly. */
private String reviewAndApproveWorkflowNode;
/** Destination folder for copy action used by these helper methods. This is populated by the getter and should not be accessed directly. */
private FolderModel copyDestinationFolder;
/** Destination folder for check out action used by these helper methods. This is populated by the getter and should not be accessed directly. */
private FolderModel checkOutDestinationFolder;
/**
* Create a rule model filled with default values.
* Get the constraint value for a given action parameter label.
*
* @param user The user to use to obtain the information.
* @param actionId The id of the action definition.
* @param paramId The id of the parameter for the action.
* @param constraintLabel The label of the desired value of the parameter.
* @return The value to use for the parameter.
*/
public String findConstraintValue(UserModel user, String actionId, String paramId, String constraintLabel)
{
RestActionConstraintModel constraintDef = getConstraintsForActionParam(user, actionId, paramId);
RestActionConstraintDataModel constraintDataModel = constraintDef.getConstraintValues().stream().filter(constraintValue -> constraintValue.getLabel().equals(constraintLabel)).findFirst().get();
return constraintDataModel.getValue();
}
/**
* Get all constraint values for a given action parameter.
*
* @param user The user to use to obtain the information.
* @param actionId The id of the action definition.
* @param paramId The id of the parameter for the action.
* @return The value to use for the parameter.
*/
public RestActionConstraintModel getConstraintsForActionParam(UserModel user, String actionId, String paramId)
{
RestActionDefinitionModel actionDef = restClient.authenticateUser(user).withCoreAPI().usingActions().getActionDefinitionById(actionId);
RestParameterDefinitionModel paramDef = actionDef.getParameterDefinitions().stream().filter(param -> param.getName().equals(paramId)).findFirst().get();
if (paramDef.getParameterConstraintName() == null)
{
throw new IllegalArgumentException("Supplied parameter " + paramId + " for action " + actionId + " does not have a defined constraint.");
}
String constraintName = paramDef.getParameterConstraintName();
return restClient.authenticateUser(user).withCoreAPI().usingActions().getActionConstraintByName(constraintName);
}
/**
* Get the review and approve workflow node (throwing an exception if this utility class has not been initialised).
*
* @return The node ref of the script node.
*/
public String getReviewAndApproveWorkflowNode()
{
if (reviewAndApproveWorkflowNode == null)
{
UserModel admin = dataUser.getAdminUser();
reviewAndApproveWorkflowNode = findConstraintValue(admin, SCRIPT_ACTION, RULE_SCRIPT_PARAM_ID, RULE_ERROR_SCRIPT_LABEL);
}
return reviewAndApproveWorkflowNode;
}
public SiteModel getPublicSite()
{
if (publicSite == null)
{
UserModel admin = dataUser.getAdminUser();
publicSite = dataSite.usingUser(admin).createPublicRandomSite();
}
return publicSite;
}
public FolderModel getCopyDestinationFolder()
{
if (copyDestinationFolder == null)
{
UserModel admin = dataUser.getAdminUser();
copyDestinationFolder = dataContent.usingUser(admin).usingSite(getPublicSite()).createFolder();
}
return copyDestinationFolder;
}
public FolderModel getCheckOutDestinationFolder()
{
if (checkOutDestinationFolder == null)
{
UserModel admin = dataUser.getAdminUser();
checkOutDestinationFolder = dataContent.usingUser(admin).usingSite(getPublicSite()).createFolder();
}
return checkOutDestinationFolder;
}
public RestRuleModel createRuleModelWithModifiedValues()
{
return createRuleModelWithModifiedValues(List.of(createAddAudioAspectAction()));
}
/**
* Create a rule model filled with custom constant values.
*
* @param actions - rule's actions.
* @return The created rule model.
*/
public static RestRuleModel createRuleModelWithModifiedValues()
public RestRuleModel createRuleModelWithModifiedValues(List<RestActionBodyExecTemplateModel> actions)
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
RestRuleModel ruleModel = createRuleModel(RULE_NAME_DEFAULT, actions);
ruleModel.setDescription(RULE_DESCRIPTION_DEFAULT);
ruleModel.setIsEnabled(RULE_ENABLED_DEFAULT);
ruleModel.setIsInheritable(RULE_CASCADE_DEFAULT);
ruleModel.setIsAsynchronous(RULE_ASYNC_DEFAULT);
ruleModel.setIsShared(RULE_SHARED_DEFAULT);
ruleModel.setTriggers(RULE_TRIGGERS_DEFAULT);
ruleModel.setErrorScript(RULE_ERROR_SCRIPT_DEFAULT);
ruleModel.setErrorScript(getReviewAndApproveWorkflowNode());
return ruleModel;
}
public static RestRuleModel createRuleModelWithDefaultValues()
public RestRuleModel createRuleModelWithDefaultValues()
{
return createRuleModel(RULE_NAME_DEFAULT, List.of(createDefaultActionModel()));
return createRuleModel(RULE_NAME_DEFAULT);
}
public static RestRuleModel createRuleModel(String name)
public RestRuleModel createRuleModel(String name)
{
return createRuleModel(name, List.of(createDefaultActionModel()));
return createRuleModel(name, List.of(createAddAudioAspectAction()));
}
/**
* Create a rule model.
*
* @param name The name for the rule.
* @param restActionModels Rule's actions.
* @param actions Rule's actions.
* @return The created rule model.
*/
public static RestRuleModel createRuleModel(String name, List<RestActionBodyExecTemplateModel> restActionModels)
public RestRuleModel createRuleModel(String name, List<RestActionBodyExecTemplateModel> actions)
{
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setIsEnabled(true);
ruleModel.setName(name);
ruleModel.setActions(restActionModels);
ruleModel.setActions(actions);
return ruleModel;
}
@@ -102,15 +239,17 @@ public class RulesTestsUtils
*
* @return The created action model.
*/
public static RestActionBodyExecTemplateModel createDefaultActionModel()
public RestActionBodyExecTemplateModel createAddAudioAspectAction()
{
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
restActionModel.setActionDefinitionId("set-property-value");
restActionModel.setParams(Map.of("aspect-name", "cm:audio"));
return restActionModel;
return createAddAspectAction(AUDIO_ASPECT);
}
public static RestActionBodyExecTemplateModel createCustomActionModel(String actionDefinitionId, Map<String, Serializable> params)
public RestActionBodyExecTemplateModel createAddAspectAction(String aspect)
{
return createCustomActionModel(ADD_FEATURES_ACTION, Map.of("aspect-name", aspect));
}
public RestActionBodyExecTemplateModel createCustomActionModel(String actionDefinitionId, Map<String, Serializable> params)
{
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
restActionModel.setActionDefinitionId(actionDefinitionId);
@@ -118,7 +257,7 @@ public class RulesTestsUtils
return restActionModel;
}
public static RestCompositeConditionDefinitionModel createEmptyConditionModel()
public RestCompositeConditionDefinitionModel createEmptyConditionModel()
{
RestCompositeConditionDefinitionModel conditions = new RestCompositeConditionDefinitionModel();
conditions.setInverted(!INVERTED);
@@ -126,7 +265,7 @@ public class RulesTestsUtils
return conditions;
}
public static RestCompositeConditionDefinitionModel createVariousConditions()
public RestCompositeConditionDefinitionModel createVariousConditions()
{
return createCompositeCondition(List.of(
createCompositeCondition(!INVERTED, List.of(
@@ -139,30 +278,40 @@ public class RulesTestsUtils
createSimpleCondition("tag", "equals", "uat")
)),
createCompositeCondition(INVERTED, List.of(
createSimpleCondition("aspect", "equals", "audio:audio"),
createSimpleCondition("aspect", "equals", AUDIO_ASPECT),
createSimpleCondition("cm:modelVersion", "begins", "1.")
))
));
}
public static RestRuleModel createVariousActions()
public RestRuleModel createRuleWithVariousActions()
{
final Map<String, Serializable> copyParams =
Map.of("destination-folder", "dummy-folder-node", "deep-copy", true);
final RestActionBodyExecTemplateModel copyAction = createCustomActionModel("copy", copyParams);
Map.of("destination-folder", getCopyDestinationFolder().getNodeRef(), "deep-copy", true);
final RestActionBodyExecTemplateModel copyAction = createCustomActionModel(COPY_ACTION, copyParams);
final Map<String, Serializable> checkOutParams =
Map.of("destination-folder", "fake-folder-node", "assoc-name", "cm:checkout", "assoc-type",
"cm:contains");
Map.of("destination-folder", getCheckOutDestinationFolder().getNodeRef(), "assoc-name", "cm:checkout",
"assoc-type", "cm:contains");
final RestActionBodyExecTemplateModel checkOutAction = createCustomActionModel("check-out", checkOutParams);
final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
// The counter action takes no parameters, so check we can omit the "params" entry.
final RestActionBodyExecTemplateModel counterAction = createCustomActionModel("counter", null);
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, scriptAction));
ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, counterAction));
return ruleModel;
}
public static RestSimpleConditionDefinitionModel createSimpleCondition(String field, String comparator, String parameter)
public RestRuleModel createRuleWithPrivateAction()
{
RestActionBodyExecTemplateModel mailAction = new RestActionBodyExecTemplateModel();
mailAction.setActionDefinitionId(MAIL_ACTION);
mailAction.setParams(createMailParameters(getRandomUserModel(), getRandomUserModel()));
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setActions(Arrays.asList(mailAction));
return ruleModel;
}
public RestSimpleConditionDefinitionModel createSimpleCondition(String field, String comparator, String parameter)
{
RestSimpleConditionDefinitionModel simpleCondition = new RestSimpleConditionDefinitionModel();
simpleCondition.setField(field);
@@ -171,18 +320,31 @@ public class RulesTestsUtils
return simpleCondition;
}
public static RestCompositeConditionDefinitionModel createCompositeCondition(List<RestCompositeConditionDefinitionModel> compositeConditions)
public RestCompositeConditionDefinitionModel createCompositeCondition(List<RestCompositeConditionDefinitionModel> compositeConditions)
{
return createCompositeCondition(AND, !INVERTED, compositeConditions, null);
}
public static RestCompositeConditionDefinitionModel createCompositeCondition(boolean inverted,
public RestCompositeConditionDefinitionModel createCompositeCondition(boolean inverted,
List<RestSimpleConditionDefinitionModel> simpleConditions)
{
return createCompositeCondition(AND, inverted, null, simpleConditions);
}
private static RestCompositeConditionDefinitionModel createCompositeCondition(String booleanMode, boolean inverted,
public RestRuleExecutionModel createRuleExecutionRequest()
{
return createRuleExecutionRequest(false);
}
public RestRuleExecutionModel createRuleExecutionRequest(boolean eachSubFolderIncluded)
{
RestRuleExecutionModel ruleExecutionBody = new RestRuleExecutionModel();
ruleExecutionBody.setIsEachSubFolderIncluded(eachSubFolderIncluded);
return ruleExecutionBody;
}
private RestCompositeConditionDefinitionModel createCompositeCondition(String booleanMode, boolean inverted,
List<RestCompositeConditionDefinitionModel> compositeConditions, List<RestSimpleConditionDefinitionModel> simpleConditions)
{
RestCompositeConditionDefinitionModel compositeCondition = new RestCompositeConditionDefinitionModel();
@@ -193,4 +355,31 @@ public class RulesTestsUtils
return compositeCondition;
}
public NodeAssertion assertThat(RestNodeModel node)
{
return new NodeAssertion(node);
}
public class NodeAssertion
{
private final RestNodeModel node;
private NodeAssertion(RestNodeModel node)
{
this.node = node;
}
public NodeAssertion containsAspects(String ...expectedAspects)
{
Arrays.stream(expectedAspects).forEach(aspect -> node.assertThat().field("aspectNames").contains(aspect));
return this;
}
public NodeAssertion notContainsAspects(String ...unexpectedAspects)
{
Arrays.stream(unexpectedAspects).forEach(aspect -> node.assertThat().field("aspectNames").notContains(aspect));
return this;
}
}
}

View File

@@ -68,8 +68,8 @@ public class SetInheritanceTests extends RestTest
STEP("Get the -isInheritanceEnabled- rule settings for the folder.");
RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(folder)
.withPrivateAPI()
.usingNode(folder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
@@ -88,13 +88,13 @@ public class SetInheritanceTests extends RestTest
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(nonExistentFolder)
.withPrivateAPI()
.usingNode(nonExistentFolder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get an error when trying to retrieve a non-existent setting. */
@@ -105,7 +105,7 @@ public class SetInheritanceTests extends RestTest
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
STEP("Try to get a fake setting from the folder.");
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingRuleSetting("-fakeRuleSetting-")
restClient.authenticateUser(siteOwner).withPrivateAPI().usingNode(folder).usingRuleSetting("-fakeRuleSetting-")
.retrieveSetting();
restClient.assertLastError().statusCodeIs(NOT_FOUND)
@@ -122,8 +122,8 @@ public class SetInheritanceTests extends RestTest
STEP("Try to get the -isInheritanceEnabled- setting without permission.");
restClient.authenticateUser(noPermissionUser)
.withCoreAPI()
.usingResource(folder)
.withPrivateAPI()
.usingNode(folder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
@@ -143,8 +143,8 @@ public class SetInheritanceTests extends RestTest
updateBody.setValue(false);
RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(folder)
.withPrivateAPI()
.usingNode(folder)
.usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
@@ -166,7 +166,7 @@ public class SetInheritanceTests extends RestTest
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue("banana");
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
restClient.authenticateUser(siteOwner).withPrivateAPI().usingNode(folder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(BAD_REQUEST)
@@ -184,11 +184,11 @@ public class SetInheritanceTests extends RestTest
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(nonExistentFolder).usingIsInheritanceEnabledRuleSetting()
restClient.authenticateUser(siteOwner).withPrivateAPI().usingNode(nonExistentFolder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get an error when trying to set a non-existent setting. */
@@ -202,7 +202,7 @@ public class SetInheritanceTests extends RestTest
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingRuleSetting("-fakeRuleSetting-")
restClient.authenticateUser(siteOwner).withPrivateAPI().usingNode(folder).usingRuleSetting("-fakeRuleSetting-")
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
@@ -223,7 +223,7 @@ public class SetInheritanceTests extends RestTest
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(collaborator).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
restClient.authenticateUser(collaborator).withPrivateAPI().usingNode(folder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(FORBIDDEN)

View File

@@ -25,6 +25,9 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.actions.access.AccessRestrictionUtil.ERROR_MESSAGE_ACCESS_RESTRICTED;
import static org.alfresco.rest.rules.RulesTestsUtils.ADD_FEATURES_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.COPY_ACTION;
import static org.alfresco.rest.rules.RulesTestsUtils.ID;
import static org.alfresco.rest.rules.RulesTestsUtils.INBOUND;
import static org.alfresco.rest.rules.RulesTestsUtils.INVERTED;
@@ -32,19 +35,10 @@ import static org.alfresco.rest.rules.RulesTestsUtils.IS_SHARED;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_ASYNC_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_CASCADE_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.RULE_ENABLED_DEFAULT;
import static org.alfresco.rest.rules.RulesTestsUtils.createCompositeCondition;
import static org.alfresco.rest.rules.RulesTestsUtils.createCustomActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithDefaultValues;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
import static org.alfresco.rest.rules.RulesTestsUtils.createSimpleCondition;
import static org.alfresco.rest.rules.RulesTestsUtils.createVariousConditions;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
@@ -95,8 +89,8 @@ public class UpdateRulesTests extends RestTest
RestRuleModel rule = createAndSaveRule("Rule name");
STEP("Try to update the rule.");
RestRuleModel updatedRuleModel = createRuleModel("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel updatedRuleModel = rulesUtils.createRuleModel("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertStatusCodeIs(OK);
@@ -117,11 +111,11 @@ public class UpdateRulesTests extends RestTest
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(nonExistentFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(nonExistentFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
.containsSummary("Folder with id fake-id was not found");
}
/** Check we get a 404 if trying to update a rule in a rule set that doesn't exist. */
@@ -133,11 +127,11 @@ public class UpdateRulesTests extends RestTest
STEP("Try to update a rule in a non-existent rule set.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingRuleSet("fake-id")
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingRuleSet("fake-id")
.updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("fake-id was not found");
.containsSummary("Rule set with id fake-id was not found");
}
/** Check we get a 404 if trying to update a rule that doesn't exist. */
@@ -147,7 +141,7 @@ public class UpdateRulesTests extends RestTest
STEP("Try to update a rule that doesn't exist.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("Updated rule name");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule("fake-id", updatedRuleModel);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
@@ -168,7 +162,7 @@ public class UpdateRulesTests extends RestTest
dataUser.addUserToSite(collaborator, privateSite, SiteCollaborator);
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(user).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
@@ -181,8 +175,8 @@ public class UpdateRulesTests extends RestTest
RestRuleModel rule = createAndSaveRule("Rule name");
STEP("Try to update the rule to have no name.");
RestRuleModel updatedRuleModel = createRuleModel("");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().updateRule(rule.getId(), updatedRuleModel);
RestRuleModel updatedRuleModel = rulesUtils.createRuleModel("");
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet().updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(BAD_REQUEST)
.containsSummary("Rule name is a mandatory parameter");
@@ -195,9 +189,9 @@ public class UpdateRulesTests extends RestTest
RestRuleModel rule = createAndSaveRule("Rule name");
STEP("Try to update the rule id and check it isn't changed.");
RestRuleModel updatedRuleModel = createRuleModel("Rule name");
RestRuleModel updatedRuleModel = rulesUtils.createRuleModel("Rule name");
updatedRuleModel.setId("new-rule-id");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), updatedRuleModel);
updatedRule.assertThat().field(ID).is(rule.getId());
@@ -210,8 +204,8 @@ public class UpdateRulesTests extends RestTest
RestRuleModel rule = createAndSaveRule("Rule name");
STEP("Try to update the rule.");
RestRuleModel updatedRuleModel = createRuleModel("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel updatedRuleModel = rulesUtils.createRuleModel("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include(IS_SHARED)
.updateRule(rule.getId(), updatedRuleModel);
@@ -228,7 +222,7 @@ public class UpdateRulesTests extends RestTest
STEP("Try to update the rule - set no actions.");
rule.setActions(null);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include(IS_SHARED)
.updateRule(rule.getId(), rule);
@@ -250,12 +244,12 @@ public class UpdateRulesTests extends RestTest
invalidAction.setActionDefinitionId(actionDefinitionId);
invalidAction.setParams(Map.of("dummy-key", "dummy-value"));
rule.setActions(List.of(invalidAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include(IS_SHARED)
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(NOT_FOUND);
restClient.assertLastError().containsSummary(actionDefinitionId);
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(String.format("Invalid rule action definition requested %s", actionDefinitionId));
}
/** Check we can use the POST response to create the new rule. */
@@ -265,19 +259,19 @@ public class UpdateRulesTests extends RestTest
FolderModel destination = dataContent.usingUser(user).usingSite(site).createFolder();
RestActionBodyExecTemplateModel copyAction = new RestActionBodyExecTemplateModel();
copyAction.setActionDefinitionId("copy");
copyAction.setActionDefinitionId(COPY_ACTION);
copyAction.setParams(ImmutableMap.of("destination-folder", destination.getNodeRef()));
RestRuleModel rule = createAndSaveRule("Rule name", List.of(copyAction));
STEP("Try to update the rule.");
rule.setName("Updated rule name");
RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include(IS_SHARED)
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
updatedRule.assertThat().field("name").is("Updated rule name")
.assertThat().field("actions.actionDefinitionId").is(List.of("copy"))
.assertThat().field("actions.actionDefinitionId").is(List.of(COPY_ACTION))
.assertThat().field("actions.params").is(List.of(ImmutableMap.of("destination-folder", destination.getNodeRef())));
}
@@ -285,7 +279,7 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleFields()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule fields.");
rule.setName("Updated rule name");
@@ -295,9 +289,8 @@ public class UpdateRulesTests extends RestTest
rule.setIsEnabled(!RULE_ENABLED_DEFAULT);
rule.setIsInheritable(!RULE_CASCADE_DEFAULT);
rule.setIsAsynchronous(!RULE_ASYNC_DEFAULT);
final String updatedErrorScript = "updated-error-script";
rule.setErrorScript(updatedErrorScript);
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
rule.setErrorScript(null);
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -309,12 +302,12 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleAddConditions()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule and add conditions.");
rule.setConditions(createVariousConditions());
rule.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -326,12 +319,12 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleAddNullConditions()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule and add null conditions.");
rule.setConditions(null);
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -343,16 +336,16 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleModifyConditions()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule and modify conditions.");
final RestCompositeConditionDefinitionModel compositeCondition = createCompositeCondition(
List.of(createCompositeCondition(false, List.of(createSimpleCondition("tag", "equals", "sample_tag")))));
final RestCompositeConditionDefinitionModel compositeCondition = rulesUtils.createCompositeCondition(
List.of(rulesUtils.createCompositeCondition(false, List.of(rulesUtils.createSimpleCondition("tag", "equals", "sample_tag")))));
rule.setConditions(compositeCondition);
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -364,14 +357,14 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleRemoveAllConditions()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule and remove all conditions.");
rule.setConditions(null);
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -383,16 +376,16 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleWithInvalidCategoryInConditionAndFail()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule with invalid condition.");
final RestCompositeConditionDefinitionModel conditions = createCompositeCondition(
List.of(createCompositeCondition(!INVERTED, List.of(createSimpleCondition("category", "equals", "fake-category-id")))));
final RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(
List.of(rulesUtils.createCompositeCondition(!INVERTED, List.of(rulesUtils.createSimpleCondition("category", "equals", "fake-category-id")))));
rule.setConditions(conditions);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -403,16 +396,16 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleWithConditionWithoutComparatorAndFail()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule with invalid condition (null comparator when required non-null).");
final RestCompositeConditionDefinitionModel conditions = createCompositeCondition(
List.of(createCompositeCondition(!INVERTED, List.of(createSimpleCondition("size", null, "65500")))));
final RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(
List.of(rulesUtils.createCompositeCondition(!INVERTED, List.of(rulesUtils.createSimpleCondition("size", null, "65500")))));
rule.setConditions(conditions);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -423,16 +416,16 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleWithConditionWithoutFieldAndFail()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule with invalid condition (null field).");
final RestCompositeConditionDefinitionModel conditions = createCompositeCondition(
List.of(createCompositeCondition(!INVERTED, List.of(createSimpleCondition(null, "greater_than", "65500")))));
final RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(
List.of(rulesUtils.createCompositeCondition(!INVERTED, List.of(rulesUtils.createSimpleCondition(null, "greater_than", "65500")))));
rule.setConditions(conditions);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -443,16 +436,16 @@ public class UpdateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleWithConditionWithoutParamValueAndFail()
{
final RestRuleModel ruleModelWithInitialValues = createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(createVariousConditions());
final RestRuleModel ruleModelWithInitialValues = rulesUtils.createRuleModelWithModifiedValues();
ruleModelWithInitialValues.setConditions(rulesUtils.createVariousConditions());
final RestRuleModel rule = createAndSaveRule(ruleModelWithInitialValues);
STEP("Try to update the rule with invalid condition (null parameter).");
final RestCompositeConditionDefinitionModel conditions = createCompositeCondition(
List.of(createCompositeCondition(!INVERTED, List.of(createSimpleCondition("size", "greater_than", "")))));
final RestCompositeConditionDefinitionModel conditions = rulesUtils.createCompositeCondition(
List.of(rulesUtils.createCompositeCondition(!INVERTED, List.of(rulesUtils.createSimpleCondition("size", "greater_than", "")))));
rule.setConditions(conditions);
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -465,17 +458,15 @@ public class UpdateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void updateRuleAddActions()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule by adding several actions");
final Map<String, Serializable> copyParams =
Map.of("destination-folder", "dummy-folder-node", "deep-copy", true);
final RestActionBodyExecTemplateModel copyAction = createCustomActionModel("copy", copyParams);
final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
rule.setActions(Arrays.asList(copyAction, scriptAction));
final RestActionBodyExecTemplateModel counterAction = rulesUtils.createCustomActionModel("counter", null);
final Map<String, Serializable> addAspectParams = Map.of("aspect-name", "cm:taggable");
final RestActionBodyExecTemplateModel addAspectAction = rulesUtils.createCustomActionModel(ADD_FEATURES_ACTION, addAspectParams);
rule.setActions(Arrays.asList(counterAction, addAspectAction));
final RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final RestRuleModel updatedRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
@@ -489,17 +480,17 @@ public class UpdateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void updateRuleAddCheckoutActionForOutboundShouldFail()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule by adding checkout action");
final Map<String, Serializable> checkOutParams =
Map.of("destination-folder", "dummy-folder-node", "assoc-name", "cm:checkout", "assoc-type",
"cm:contains");
final RestActionBodyExecTemplateModel checkOutAction = createCustomActionModel("check-out", checkOutParams);
final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
Map.of("destination-folder", rulesUtils.getCheckOutDestinationFolder().getNodeRef(), "assoc-name", "cm:checkout",
"assoc-type", "cm:contains");
final RestActionBodyExecTemplateModel checkOutAction = rulesUtils.createCustomActionModel("check-out", checkOutParams);
rule.setActions(List.of(checkOutAction));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
final UserModel admin = dataUser.getAdminUser();
restClient.authenticateUser(admin).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(BAD_REQUEST);
@@ -513,24 +504,62 @@ public class UpdateRulesTests extends RestTest
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void updateRuleAddActionWithInvalidParamShouldFail()
{
final RestRuleModel rule = createAndSaveRule(createRuleModelWithModifiedValues());
final RestRuleModel rule = createAndSaveRule(rulesUtils.createRuleModelWithModifiedValues());
STEP("Try to update the rule by adding action with invalid parameter (non-existing namespace in value)");
final RestActionBodyExecTemplateModel action = new RestActionBodyExecTemplateModel();
action.setActionDefinitionId("add-features");
action.setParams(Map.of("aspect-name", "dummy:dummy"));
action.setActionDefinitionId(ADD_FEATURES_ACTION);
final String aspectNameParam = "aspect-name";
final String paramValue = "dummy:dummy";
action.setParams(Map.of(aspectNameParam, paramValue));
rule.setActions(List.of(action));
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(INTERNAL_SERVER_ERROR);
restClient.assertLastError().containsSummary("Namespace prefix dummy is not mapped to a namespace URI");
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary(
String.format("Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s",
aspectNameParam, paramValue, "ac-aspects"));
}
/** Check that a normal user cannot create rules that use private actions. */
@Test
public void updateRuleWithActions_userCannotUsePrivateAction()
{
STEP("Using admin create a rule with a private action.");
RestRuleModel rule = restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
STEP("Try to update the rule with a normal user.");
rule.setName("Updated name");
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(FORBIDDEN)
.assertLastError().containsSummary(ERROR_MESSAGE_ACCESS_RESTRICTED);
}
/** Check that an administrator can create rules that use private actions. */
@Test
public void updateRuleWithActions_adminCanUsePrivateAction()
{
STEP("Using admin create a rule with a private action.");
RestRuleModel rule = restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleWithPrivateAction());
STEP("Try to update the rule with the admin user.");
rule.setName("Updated name");
RestRuleModel updatedRule = restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.updateRule(rule.getId(), rule);
restClient.assertStatusCodeIs(OK);
updatedRule.assertThat().field("name").is("Updated name");
}
private RestRuleModel createAndSaveRule(String name)
{
return createAndSaveRule(name, List.of(createDefaultActionModel()));
return createAndSaveRule(name, List.of(rulesUtils.createAddAudioAspectAction()));
}
/**
@@ -543,8 +572,8 @@ public class UpdateRulesTests extends RestTest
private RestRuleModel createAndSaveRule(String name, List<RestActionBodyExecTemplateModel> restActionModels)
{
STEP("Create a rule called " + name + ", containing actions: " + restActionModels);
RestRuleModel ruleModel = createRuleModel(name, restActionModels);
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel(name, restActionModels);
return restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
}
@@ -557,7 +586,7 @@ public class UpdateRulesTests extends RestTest
private RestRuleModel createAndSaveRule(final RestRuleModel ruleModel)
{
STEP("Create a rule: " + ruleModel);
return restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
return restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
}
}

View File

@@ -9,7 +9,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-tests</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<developers>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo-packaging</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<properties>

View File

@@ -139,6 +139,33 @@
<param name="cookie">{token}</param>
</action>
</rule>
<rule>
<request>
<method>GET</method>
<path>/s/index|/s/</path>
</request>
<action name="generateToken">
<param name="session">{token}</param>
<param name="cookie">{token}</param>
</action>
</rule>
<rule>
<request>
<method>POST</method>
<path>/s/index|/s/</path>
</request>
<action name="assertToken">
<param name="session">{token}</param>
<param name="parameter">{token}</param>
</action>
<action name="assertReferer">
<param name="referer">{referer}</param>
</action>
<action name="assertOrigin">
<param name="origin">{origin}</param>
</action>
</rule>
<!--
Verify multipart requests contain the token as a parameter

View File

@@ -231,6 +231,12 @@
<url-pattern>/wcs/admin/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CSRF Token Filter</filter-name>
<url-pattern>/s/index</url-pattern>
<url-pattern>/s/</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Security Headers Filter</filter-name>
<url-pattern>/*</url-pattern>

View File

@@ -71,7 +71,7 @@ ModuleDetails shareServicesModule = moduleService.getModule("alfresco-share-serv
</div>
<div class="index-list">
<h4><%=descriptorService.getServerDescriptor().getEdition()%>&nbsp;-&nbsp;<%=descriptorService.getServerDescriptor().getVersion()%></h4>
<h4><%=descriptorService.getServerDescriptor().getEdition()%></h4>
<p></p>
<p><a href="http://docs.alfresco.com/">Online Documentation</a></p>
<p></p>

25
pom.xml
View File

@@ -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>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -25,7 +25,7 @@
<properties>
<acs.version.major>7</acs.version.major>
<acs.version.minor>3</acs.version.minor>
<acs.version.revision>0</acs.version.revision>
<acs.version.revision>1</acs.version.revision>
<acs.version.label />
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
@@ -51,18 +51,17 @@
<dependency.alfresco-log-sanitizer.version>0.2</dependency.alfresco-log-sanitizer.version>
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.alfresco-transform-service.version>2.0.0-A3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0-A3</dependency.alfresco-transform-core.version>
<dependency.alfresco-transform-service.version>2.0.0</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0</dependency.alfresco-transform-core.version>
<dependency.alfresco-greenmail.version>6.4</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
<dependency.spring.version>5.3.23</dependency.spring.version>
<dependency.antlr.version>3.5.3</dependency.antlr.version>
<dependency.jackson.version>2.13.3</dependency.jackson.version>
<dependency.jackson-databind.version>2.13.3</dependency.jackson-databind.version>
<dependency.jackson.version>2.14.0-rc1</dependency.jackson.version>
<dependency.cxf.version>3.5.3</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.32</dependency.webscripts.version>
<dependency.webscripts.version>8.33</dependency.webscripts.version>
<dependency.bouncycastle.version>1.70</dependency.bouncycastle.version>
<dependency.mockito-core.version>4.6.1</dependency.mockito-core.version>
<dependency.assertj.version>3.23.1</dependency.assertj.version>
@@ -81,7 +80,7 @@
<dependency.spring-security.version>5.7.3</dependency.spring-security.version>
<dependency.truezip.version>7.7.10</dependency.truezip.version>
<dependency.poi.version>5.2.2</dependency.poi.version>
<dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
<dependency.poi-ooxml-lite.version>5.2.3</dependency.poi-ooxml-lite.version>
<dependency.keycloak.version>18.0.0</dependency.keycloak.version>
<dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
<dependency.camel.version>3.18.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
@@ -110,9 +109,9 @@
<dependency.jakarta-json-path.version>2.7.0</dependency.jakarta-json-path.version>
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
<alfresco.googledrive.version>3.2.3-A2</alfresco.googledrive.version>
<alfresco.aos-module.version>1.4.1</alfresco.aos-module.version>
<alfresco.api-explorer.version>7.2.1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.googledrive.version>3.3.0</alfresco.googledrive.version>
<alfresco.aos-module.version>1.5.0</alfresco.aos-module.version>
<alfresco.api-explorer.version>7.3.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.0.1.alfresco-2</license-maven-plugin.version>
@@ -123,7 +122,7 @@
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.56</dependency.tas-utility.version>
<dependency.rest-assured.version>5.2.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.124</dependency.tas-restapi.version>
<dependency.tas-restapi.version>1.135</dependency.tas-restapi.version>
<dependency.tas-email.version>1.9</dependency.tas-email.version>
<dependency.tas-webdav.version>1.7</dependency.tas-webdav.version>
<dependency.tas-ftp.version>1.7</dependency.tas-ftp.version>
@@ -503,7 +502,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${dependency.jackson-databind.version}</version>
<version>${dependency.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.141-SNAPSHOT</version>
<version>18.8-SNAPSHOT</version>
</parent>
<dependencies>

View File

@@ -121,6 +121,13 @@ public class WebDAVServlet extends HttpServlet
startTime = System.currentTimeMillis();
}
if (request.getMethod().equals(WebDAV.METHOD_POST) && !initParams.allowInsecurePOSTMethod())
{
logger.error("POST method is not allowed!");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
FileFilterMode.setClient(Client.webdav);
try
@@ -407,6 +414,7 @@ public class WebDAVServlet extends HttpServlet
private String storeName;
private String rootPath;
private String urlPathPrefix;
private boolean allowInsecurePOSTMethod = false;
public boolean getEnabled()
{
@@ -482,5 +490,15 @@ public class WebDAVServlet extends HttpServlet
{
this.urlPathPrefix = urlPathPrefix;
}
public boolean allowInsecurePOSTMethod()
{
return allowInsecurePOSTMethod;
}
public void setAllowInsecurePOSTMethod(boolean allowInsecurePOSTMethod)
{
this.allowInsecurePOSTMethod = allowInsecurePOSTMethod;
}
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -27,10 +27,14 @@
package org.alfresco.rest.api;
import java.util.List;
import org.alfresco.rest.api.model.Action;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
public interface Actions
@@ -45,7 +49,12 @@ public interface Actions
{
NAME,
TITLE
};
}
Action executeAction(Action action, Parameters parameters);
@Experimental
ActionParameterConstraint getActionConstraint(String constraintName);
@Experimental
ActionDefinition getRuleActionDefinitionById(String actionDefinitionId);
}

View File

@@ -59,6 +59,16 @@ public interface RuleSets
*/
RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes);
/**
* Update a rule set - for example to reorder the rules within it.
*
* @param folderNodeId Folder node ID
* @param ruleSet The updated rule set.
* @param includes List of fields to include in the response.
* @return The updated rule set from the server.
*/
RuleSet updateRuleSet(String folderNodeId, RuleSet ruleSet, List<String> includes);
/**
* Link a rule set to a folder
*/

View File

@@ -29,6 +29,7 @@ package org.alfresco.rest.api;
import java.util.List;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleExecution;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
@@ -65,10 +66,10 @@ public interface Rules
Rule getRuleById(String folderNodeId, String ruleSetId, String ruleId, List<String> includes);
/**
* Create new rules (and potentially a rule set if "_default_" is supplied).
* Create new rules (and potentially a rule set if "-default-" is supplied).
*
* @param folderNodeId The node id of a folder.
* @param ruleSetId The id of a rule set (or "_default_" to use/create the default rule set for the folder).
* @param ruleSetId The id of a rule set (or "-default-" to use/create the default rule set for the folder).
* @param rule The definition of the rule.
* @param includes The list of optional fields to include in the response.
* @return The newly created rules.
@@ -81,7 +82,7 @@ public interface Rules
* Update a rule.
*
* @param folderNodeId The id of a folder.
* @param ruleSetId The id of a rule set within the folder (or "_default_" to use the default rule set for the folder).
* @param ruleSetId The id of a rule set within the folder (or "-default-" to use the default rule set for the folder).
* @param ruleId The rule id.
* @param rule The new version of the rule.
* @param includes The list of optional fields to include in the response.
@@ -94,7 +95,15 @@ public interface Rules
*
* @param folderNodeId - folder node ID
* @param ruleSetId - rule set ID
* @param ruleId - rule ID *
* @param ruleId - rule ID
*/
void deleteRuleById(String folderNodeId, String ruleSetId, String ruleId);
/**
* Execute rules for given folder node.
*
* @param folderNodeId - the ID of a folder
* @param eachSubFolderIncluded - indicates if rules should be executed also on sub-folders
*/
RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded);
}

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2017 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.api.actions;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
@EntityResource(name="action-constraints", title = "Action parameter constraints")
@Experimental
public class ActionConstraintsEntityResource implements EntityResourceAction.ReadById<ActionParameterConstraint>
{
private final Actions actions;
public ActionConstraintsEntityResource(Actions actions)
{
this.actions = actions;
}
@WebApiDescription(title = "Get single action parameters constraint",
description = "Retrieves a single action parameters constraint by constraint name",
successStatus = HttpServletResponse.SC_OK)
@Experimental
@Override
public ActionParameterConstraint readById(String constraintName, Parameters parameters) throws EntityNotFoundException
{
return actions.getActionConstraint(constraintName);
}
}

View File

@@ -0,0 +1,59 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
@EntityResource(name="action-parameter-constraints", title = "Action parameter constraints")
@Experimental
public class ActionParameterConstraintsEntityResource implements EntityResourceAction.ReadById<ActionParameterConstraint>
{
private final Actions actions;
public ActionParameterConstraintsEntityResource(Actions actions)
{
this.actions = actions;
}
@WebApiDescription(title = "Get single action parameter constraint",
description = "Retrieves a single action parameter constraint by constraint name",
successStatus = HttpServletResponse.SC_OK)
@Experimental
@Override
public ActionParameterConstraint readById(String constraintName, Parameters parameters) throws EntityNotFoundException
{
return actions.getActionConstraint(constraintName);
}
}

View File

@@ -0,0 +1,60 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import java.util.List;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
@Experimental
public interface ActionValidator
{
String ALL_ACTIONS = "all";
/**
* Provides validation logic for given action.
*/
void validate(Action action);
/**
* Returns priority of validator (applied to bulk validation in @see {@link org.alfresco.rest.api.impl.mapper.rules.RestRuleActionModelMapper})
* The lower number, the higher priority is set for the validator.
* @return priority expressed as int
*/
int getPriority();
/**
* By default validator is applied to all actions
*
* @return indicator for all defined action definition ids
*/
default List<String> getActionDefinitionIds() {
return List.of(ALL_ACTIONS);
}
}

View File

@@ -27,15 +27,22 @@ package org.alfresco.rest.api.impl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.constraint.FolderContentsParameterConstraint;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.Action;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.resource.parameters.SortColumn;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ParameterConstraint;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
@@ -59,6 +66,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -68,11 +76,14 @@ import static java.util.Comparator.nullsFirst;
public class ActionsImpl implements Actions
{
static final String CONSTRAINT_NOT_EXISTS = "Action parameter constraints for name %s do not exist.";
private ActionService actionService;
private DictionaryService dictionaryService;
private NamespaceService namespaceService;
private NodeService nodeService;
private NamespacePrefixResolver prefixResolver;
private ActionParameterConverter actionParameterConverter;
public void setActionService(ActionService actionService)
{
@@ -99,6 +110,11 @@ public class ActionsImpl implements Actions
this.prefixResolver = prefixResolver;
}
public void setActionParameterConverter(ActionParameterConverter actionParameterConverter)
{
this.actionParameterConverter = actionParameterConverter;
}
@Override
public ActionDefinition getActionDefinitionById(String actionDefinitionId)
{
@@ -125,27 +141,13 @@ public class ActionsImpl implements Actions
return result;
}
private ActionDefinition getActionDefinition(
private ActionDefinition getActionDefinition(
org.alfresco.service.cmr.action.ActionDefinition actionDefinitionId)
{
List<ActionDefinition.ParameterDefinition> paramDefs =
actionDefinitionId.
getParameterDefinitions().
stream().
map(this::toModel).
collect(Collectors.toList());
return new ActionDefinition(
actionDefinitionId.getName(), // ID is a synonym for name.
actionDefinitionId.getName(),
actionDefinitionId.getTitle(),
actionDefinitionId.getDescription(),
toShortQNames(actionDefinitionId.getApplicableTypes()),
actionDefinitionId.getAdhocPropertiesAllowed(),
actionDefinitionId.getTrackStatus(),
paramDefs);
{
return mapFromServiceModel(actionDefinitionId);
}
@Override
public CollectionWithPagingInfo<ActionDefinition> getActionDefinitions(NodeRef nodeRef, Parameters params)
{
@@ -174,7 +176,7 @@ public class ActionsImpl implements Actions
sortKey = Actions.SortKey.valueOf(sorting.get(0).column.toUpperCase());
sortAsc = sorting.get(0).asc;
}
Comparator<? super ActionDefinition> comparator;
switch (sortKey)
{
@@ -187,7 +189,7 @@ public class ActionsImpl implements Actions
default:
throw new IllegalArgumentException("Invalid sort key, must be either 'title' or 'name'.");
}
if (!sortAsc)
{
comparator = comparator.reversed();
@@ -199,28 +201,12 @@ public class ActionsImpl implements Actions
List<ActionDefinition> sortedPage = actionDefinitions.
stream().
map(actionDefinition -> {
List<ActionDefinition.ParameterDefinition> paramDefs =
actionDefinition.
getParameterDefinitions().
stream().
map(this::toModel).
collect(Collectors.toList());
return new ActionDefinition(
actionDefinition.getName(), // ID is a synonym for name.
actionDefinition.getName(),
actionDefinition.getTitle(),
actionDefinition.getDescription(),
toShortQNames(actionDefinition.getApplicableTypes()),
actionDefinition.getAdhocPropertiesAllowed(),
actionDefinition.getTrackStatus(),
paramDefs);
}).
map(this::mapFromServiceModel).
sorted(comparator).
skip(skip).
limit(maxItems).
collect(Collectors.toList());
boolean hasMoreItems = actionDefinitions.size() > (skip + maxItems);
return CollectionWithPagingInfo.asPaged(
@@ -230,6 +216,40 @@ public class ActionsImpl implements Actions
actionDefinitions.size());
}
@Override
@Experimental
public ActionDefinition getRuleActionDefinitionById(String actionDefinitionId)
{
if (actionDefinitionId == null)
{
throw new InvalidArgumentException("actionDefinitionId is null");
}
return actionService.getActionDefinitions().stream()
.filter(a -> actionDefinitionId.equals(a.getName()))
.map(this::mapFromServiceModel)
.findFirst()
.orElseThrow(() -> new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[] {actionDefinitionId}));
}
private ActionDefinition mapFromServiceModel(org.alfresco.service.cmr.action.ActionDefinition actionDefinition)
{
List<ActionDefinition.ParameterDefinition> paramDefs =
actionDefinition.
getParameterDefinitions().
stream().
map(this::toModel).
collect(Collectors.toList());
return new ActionDefinition(
actionDefinition.getName(), // ID is a synonym for name.
actionDefinition.getName(),
actionDefinition.getTitle(),
actionDefinition.getDescription(),
toShortQNames(actionDefinition.getApplicableTypes()),
actionDefinition.getAdhocPropertiesAllowed(),
actionDefinition.getTrackStatus(),
paramDefs);
}
@Override
public Action executeAction(Action action, Parameters parameters)
{
@@ -297,6 +317,52 @@ public class ActionsImpl implements Actions
return result;
}
@Override
@Experimental
public ActionParameterConstraint getActionConstraint(String constraintName)
{
final ParameterConstraint parameterConstraint = actionService.getParameterConstraint(constraintName);
if (Objects.isNull(parameterConstraint))
{
throw new NotFoundException(String.format(CONSTRAINT_NOT_EXISTS, constraintName));
}
return mapToActionConstraint(parameterConstraint);
}
@Experimental
private ActionParameterConstraint mapToActionConstraint(ParameterConstraint parameterConstraint)
{
final ActionParameterConstraint constraint = new ActionParameterConstraint();
constraint.setConstraintName(parameterConstraint.getName());
constraint.setConstraintValues(getConstraintDataList(parameterConstraint));
return constraint;
}
@Experimental
private List<ActionParameterConstraint.ConstraintData> getConstraintDataList(final ParameterConstraint parameterConstraint)
{
final Map<String, String> constraintValues = parameterConstraint.getValues();
if (parameterConstraint instanceof FolderContentsParameterConstraint)
{
return convertNodeRefConstraintValues(constraintValues).entrySet().stream()
.map(e -> new ActionParameterConstraint.ConstraintData(e.getKey(), e.getValue()))
.collect(Collectors.toList());
} else
{
return constraintValues.entrySet().stream()
.map(e -> new ActionParameterConstraint.ConstraintData(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}
}
@Experimental
private Map<String, String> convertNodeRefConstraintValues(final Map<String, String> inputValues)
{
return inputValues.entrySet().stream()
.collect(Collectors.toMap(e -> actionParameterConverter.convertParamFromServiceModel(new NodeRef(e.getKey())).toString(),
Map.Entry::getValue));
}
private Map<String, Serializable> extractActionParams(org.alfresco.service.cmr.action.ActionDefinition actionDefinition, Map<String, String> params)
{
Map<String, Serializable> parameterValues = new HashMap<>();

View File

@@ -295,7 +295,18 @@ public class AuditImpl implements Audit
}
else
{
totalItems = hasMoreItems ? getAuditEntriesCountByApp(auditApplication) : totalRetrievedItems;
if (hasMoreItems) {
if (q != null) {
// filtering via "where" clause
AuditEntryQueryWalker propertyWalker = new AuditEntryQueryWalker();
QueryHelper.walk(q, propertyWalker);
totalItems = getAuditEntriesCountByAppAndProperties(auditApplication, propertyWalker);
} else {
totalItems = getAuditEntriesCountByApp(auditApplication);
}
} else {
totalItems = totalRetrievedItems;
}
}
entriesAudit = (skipCount >= totalRetrievedItems)
@@ -895,4 +906,19 @@ public class AuditImpl implements Audit
final String applicationName = auditApplication.getKey().substring(1);
return auditService.getAuditEntriesCountByApp(applicationName);
}
public int getAuditEntriesCountByAppAndProperties(AuditService.AuditApplication auditApplication, AuditEntryQueryWalker propertyWalker)
{
final String applicationName = auditApplication.getKey().substring(1);
AuditQueryParameters parameters = new AuditQueryParameters();
parameters.setApplicationName(applicationName);
parameters.setFromTime(propertyWalker.getFromTime());
parameters.setToTime(propertyWalker.getToTime());
parameters.setFromId(propertyWalker.getFromId());
parameters.setToId(propertyWalker.getToId());
parameters.setUser(propertyWalker.getCreatedByUser());
return auditService.getAuditEntriesCountByAppAndProperties(applicationName, parameters);
}
}

View File

@@ -400,12 +400,10 @@ public class NodesImpl implements Nodes
@Override
public NodeRef validateNode(StoreRef storeRef, String nodeId)
{
String versionLabel = null;
int idx = nodeId.indexOf(";");
if (idx != -1)
{
versionLabel = nodeId.substring(idx + 1);
String versionLabel = nodeId.substring(idx + 1);
nodeId = nodeId.substring(0, idx);
if (versionLabel.equals("pwc"))
{
@@ -1753,7 +1751,7 @@ public class NodesImpl implements Nodes
// default false (if not provided)
boolean permanentDelete = Boolean.valueOf(parameters.getParameter(PARAM_PERMANENT));
if (permanentDelete == true)
if (permanentDelete)
{
boolean isAdmin = authorityService.hasAdminAuthority();
if (! isAdmin)

View File

@@ -26,15 +26,22 @@
package org.alfresco.rest.api.impl.mapper.rules;
import static java.util.Collections.emptyMap;
import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME;
import static org.alfresco.rest.api.actions.ActionValidator.ALL_ACTIONS;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Optional;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.Action;
@@ -46,10 +53,13 @@ import org.apache.commons.collections.CollectionUtils;
public class RestRuleActionModelMapper implements RestModelMapper<Action, org.alfresco.service.cmr.action.Action>
{
private final ActionParameterConverter parameterConverter;
private final List<ActionValidator> actionValidators;
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter)
public RestRuleActionModelMapper(ActionParameterConverter parameterConverter,
List<ActionValidator> actionValidators)
{
this.parameterConverter = parameterConverter;
this.actionValidators = actionValidators;
}
/**
@@ -72,7 +82,7 @@ public class RestRuleActionModelMapper implements RestModelMapper<Action, org.al
final Map<String, Serializable> convertedParams = actionModel.getParameterValues()
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> parameterConverter.convertParamFromServiceModel(e.getValue())));
.collect(HashMap::new, (m, v) -> m.put(v.getKey(), parameterConverter.convertParamFromServiceModel(v.getValue())), HashMap::putAll);
convertedParams.remove(ACTION_CONTEXT_PARAM_NAME);
builder.params(convertedParams);
}
@@ -100,8 +110,17 @@ public class RestRuleActionModelMapper implements RestModelMapper<Action, org.al
private org.alfresco.service.cmr.action.Action toServiceAction(Action action)
{
final Map<String, Serializable> params = Optional.ofNullable(action.getParams()).orElse(emptyMap());
validateAction(action);
final Map<String, Serializable> convertedParams =
parameterConverter.getConvertedParams(action.getParams(), action.getActionDefinitionId());
parameterConverter.getConvertedParams(params, action.getActionDefinitionId());
return new ActionImpl(null, GUID.generate(), action.getActionDefinitionId(), convertedParams);
}
private void validateAction(Action action) {
actionValidators.stream()
.filter(v -> (v.getActionDefinitionIds().contains(action.getActionDefinitionId()) ||
v.getActionDefinitionIds().equals(List.of(ALL_ACTIONS))))
.sorted(Comparator.comparing(ActionValidator::getPriority))
.forEachOrdered(v -> v.validate(action));
}
}

View File

@@ -26,12 +26,18 @@
package org.alfresco.rest.api.impl.rules;
import static org.alfresco.rest.framework.core.exceptions.NotFoundException.DEFAULT_MESSAGE_ID;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
@@ -42,10 +48,11 @@ import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.logging.log4j.util.Strings;
import org.json.JSONArray;
import org.json.JSONException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -53,16 +60,22 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@Experimental
public class ActionParameterConverter
{
static final String ACTION_PARAMETER_SHOULD_NOT_HAVE_EMPTY_OR_NULL_VALUE =
"Action parameter should not have empty or null value";
private final DictionaryService dictionaryService;
private final ActionService actionService;
private final NamespaceService namespaceService;
private final PermissionService permissionService;
private final Nodes nodes;
public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService,
NamespaceService namespaceService)
public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService, NamespaceService namespaceService,
PermissionService permissionService, Nodes nodes)
{
this.dictionaryService = dictionaryService;
this.actionService = actionService;
this.namespaceService = namespaceService;
this.permissionService = permissionService;
this.nodes = nodes;
}
public Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
@@ -74,14 +87,19 @@ public class ActionParameterConverter
definition = actionService.getActionDefinition(name);
if (definition == null)
{
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{name});
}
} catch (NoSuchBeanDefinitionException e) {
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
}
catch (NoSuchBeanDefinitionException e)
{
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{name});
}
for (Map.Entry<String, Serializable> param : params.entrySet())
{
if (Objects.toString(param.getValue(), Strings.EMPTY).isEmpty()) {
throw new InvalidArgumentException(ACTION_PARAMETER_SHOULD_NOT_HAVE_EMPTY_OR_NULL_VALUE, new String[] {param.getKey()});
}
final ParameterDefinition paramDef = definition.getParameterDefintion(param.getKey());
if (paramDef == null && !definition.getAdhocPropertiesAllowed())
{
@@ -91,7 +109,8 @@ public class ActionParameterConverter
{
final QName typeQName = paramDef.getType();
parameters.put(param.getKey(), convertValue(typeQName, param.getValue()));
} else
}
else
{
parameters.put(param.getKey(), param.getValue().toString());
}
@@ -105,7 +124,8 @@ public class ActionParameterConverter
{
return ((QName) param).toPrefixString(namespaceService);
}
else if (param instanceof NodeRef) {
else if (param instanceof NodeRef)
{
return ((NodeRef) param).getId();
}
else
@@ -121,7 +141,7 @@ public class ActionParameterConverter
final DataTypeDefinition typeDef = dictionaryService.getDataType(typeQName);
if (typeDef == null)
{
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
throw new NotFoundException(DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
}
if (propertyValue instanceof JSONArray)
@@ -130,7 +150,8 @@ public class ActionParameterConverter
try
{
Class.forName(javaClassName);
} catch (ClassNotFoundException e)
}
catch (ClassNotFoundException e)
{
throw new DictionaryException("Java class " + javaClassName + " of property type " + typeDef.getName() + " is invalid", e);
}
@@ -145,13 +166,19 @@ public class ActionParameterConverter
}
else
{
if (typeQName.equals(DataTypeDefinition.QNAME) && typeQName.toString().contains(":"))
final String stringValue = Objects.toString(propertyValue, Strings.EMPTY);
if (typeQName.isMatch(DataTypeDefinition.QNAME) && typeQName.toString().contains(":"))
{
value = QName.createQName(propertyValue.toString(), namespaceService);
value = QName.createQName(stringValue, namespaceService);
}
else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
{
value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, propertyValue.toString());
NodeRef nodeRef = nodes.validateOrLookupNode(stringValue, null);
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
{
throw new EntityNotFoundException(stringValue);
}
value = nodeRef;
}
else
{

View File

@@ -35,6 +35,7 @@ import org.alfresco.repo.rule.RuleModel;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
@@ -65,14 +66,21 @@ public class NodeValidator
* @return folder node reference
* @throws InvalidArgumentException if node is not of an expected type
* @throws PermissionDeniedException if the user doesn't have the appropriate permission for the folder.
* @throws EntityNotFoundException if the folder node isn't found
*/
public NodeRef validateFolderNode(final String folderNodeId, boolean requireChangePermission)
{
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
validatePermission(requireChangePermission, nodeRef);
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
try
{
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
validatePermission(requireChangePermission, nodeRef);
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
return nodeRef;
return nodeRef;
} catch (EntityNotFoundException e)
{
throw new EntityNotFoundException("Folder with id " + folderNodeId + " was not found.", e);
}
}
/**
@@ -82,6 +90,8 @@ public class NodeValidator
* @param associatedFolderNodeRef - folder node ref to check the association
* @return rule set node reference
* @throws InvalidArgumentException in case of not matching associated folder node
* @throws RelationshipResourceNotFoundException if the folder doesn't have a -default- rule set
* @throws EntityNotFoundException if the rule set node isn't found
*/
public NodeRef validateRuleSetNode(final String ruleSetId, final NodeRef associatedFolderNodeRef)
{
@@ -96,13 +106,18 @@ public class NodeValidator
return ruleSetNodeRef;
}
final NodeRef ruleSetNodeRef = validateNode(ruleSetId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef))
{
throw new InvalidArgumentException("Rule set is not associated with folder node!");
}
try {
final NodeRef ruleSetNodeRef = validateNode(ruleSetId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
return ruleSetNodeRef;
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef))
{
throw new InvalidArgumentException("Rule set is not associated with folder node!");
}
return ruleSetNodeRef;
} catch (EntityNotFoundException e) {
throw new EntityNotFoundException("Rule set with id " + ruleSetId + " was not found.", e);
}
}
public NodeRef validateRuleSetNode(String linkToNodeId, boolean requireChangePermission)

View File

@@ -25,6 +25,8 @@
*/
package org.alfresco.rest.api.impl.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.api.model.rules.InclusionType.INHERITED;
import static org.alfresco.rest.api.model.rules.InclusionType.LINKED;
import static org.alfresco.rest.api.model.rules.InclusionType.OWNED;
@@ -32,6 +34,7 @@ import static org.alfresco.rest.api.model.rules.InclusionType.OWNED;
import java.util.List;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.rest.api.impl.mapper.rules.RestRuleModelMapper;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -49,7 +52,9 @@ public class RuleSetLoader
protected static final String LINKED_TO_BY = "linkedToBy";
protected static final String IS_INHERITED = "isInherited";
protected static final String IS_LINKED_TO = "isLinkedTo";
protected static final String RULE_IDS = "ruleIds";
private static final int MAX_INHERITED_BY_SIZE = 100;
private static final int MAX_LINKED_TO_BY_SIZE = 100;
private NodeService nodeService;
private RuleService ruleService;
@@ -103,6 +108,10 @@ public class RuleSetLoader
{
ruleSet.setIsLinkedTo(loadIsLinkedTo(ruleSetNodeRef, parentRef));
}
if (includes.contains(RULE_IDS))
{
ruleSet.setRuleIds(loadRuleIds(parentRef));
}
}
return ruleSet;
}
@@ -114,7 +123,7 @@ public class RuleSetLoader
private List<NodeRef> loadLinkedToBy(NodeRef ruleSetNodeRef)
{
return ruleService.getFoldersLinkingToRuleSet(ruleSetNodeRef);
return ruleService.getFoldersLinkingToRuleSet(ruleSetNodeRef, MAX_LINKED_TO_BY_SIZE);
}
private boolean loadIsInherited(NodeRef ruleSetNodeRef)
@@ -139,6 +148,14 @@ public class RuleSetLoader
);
}
public List<String> loadRuleIds(NodeRef folderNodeRef)
{
return ruleService.getRules(folderNodeRef, false).stream()
.map(org.alfresco.service.cmr.rule.Rule::getNodeRef)
.map(NodeRef::getId)
.collect(toList());
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
@@ -148,4 +165,5 @@ public class RuleSetLoader
{
this.ruleService = ruleService;
}
}

View File

@@ -28,11 +28,18 @@ package org.alfresco.rest.api.impl.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.alfresco.util.collections.CollectionUtils.isEmpty;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.IntStream;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.repo.rule.RuntimeRuleService;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.api.model.rules.RuleSetLink;
@@ -41,14 +48,17 @@ import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.AspectMissingException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Experimental
public class RuleSetsImpl implements RuleSets
{
private static final Logger LOGGER = LoggerFactory.getLogger(RuleSetsImpl.class);
private RuleSetLoader ruleSetLoader;
private RuleService ruleService;
private NodeValidator validator;
@@ -62,15 +72,42 @@ public class RuleSetsImpl implements RuleSets
List<RuleSet> ruleSets = ruleService.getNodesSupplyingRuleSets(folderNode)
.stream()
.map(ruleService::getRuleSetNode)
.map(supplyingNode -> loadRuleSet(supplyingNode, folderNode, includes))
.filter(Objects::nonNull)
.map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
.distinct()
.collect(toList());
return ListPage.of(ruleSets, paging);
}
/**
* Load the specified rule set if the user has permission.
*
* @param supplyingNode The folder supplying a rule set.
* @param folderNode The folder being supplied with rule sets.
* @param includes The list of optional fields to include for each rule set in the response.
* @return The rule set from the DB or null if the folder has no rule set, or the current user does not have permission to view it.
*/
private RuleSet loadRuleSet(NodeRef supplyingNode, NodeRef folderNode, List<String> includes)
{
NodeRef ruleSetNode = ruleService.getRuleSetNode(supplyingNode);
// Check if the folder has no rule sets.
if (ruleSetNode == null)
{
return null;
}
try
{
return ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
}
catch (AccessDeniedException e)
{
LOGGER.debug("User does not have permission to view rule set with id {}.", ruleSetNode, e);
return null;
}
}
@Override
public RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes)
{
@@ -80,6 +117,43 @@ public class RuleSetsImpl implements RuleSets
return ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
}
@Override
public RuleSet updateRuleSet(String folderNodeId, RuleSet ruleSet, List<String> includes)
{
// Editing the order of the rules doesn't require permission to edit the rule set itself.
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSet.getId(), folderNode);
RuleSet returnedRuleSet = ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
// Currently the only field that can be updated is ruleIds to reorder the rules.
List<String> suppliedRuleIds = ruleSet.getRuleIds();
if (!isEmpty(suppliedRuleIds))
{
// Check there are no duplicate rule ids in the request.
Set<String> suppliedRuleIdSet = new HashSet<>(suppliedRuleIds);
// Check that the set of rule ids hasn't changed.
Set<String> existingRuleIds = new HashSet<>(ruleSetLoader.loadRuleIds(folderNode));
if (suppliedRuleIdSet.size() != suppliedRuleIds.size() || !suppliedRuleIdSet.equals(existingRuleIds))
{
throw new InvalidArgumentException("Unexpected set of rule ids - received " + suppliedRuleIds + " but expected " + existingRuleIds);
}
IntStream.range(0, suppliedRuleIds.size()).forEach(index ->
{
NodeRef ruleNode = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, suppliedRuleIds.get(index));
ruleService.setRulePosition(folderNode, ruleNode, index);
});
if (includes.contains(RuleSetLoader.RULE_IDS))
{
returnedRuleSet.setRuleIds(suppliedRuleIds);
}
}
return returnedRuleSet;
}
@Override
public RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId)
{
@@ -87,8 +161,8 @@ public class RuleSetsImpl implements RuleSets
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId,true);
final boolean isRuleSetNode = validator.isRuleSetNode(linkToNodeId);
final NodeRef linkToNodeRef = isRuleSetNode
? validator.validateRuleSetNode(linkToNodeId, true)
: validator.validateFolderNode(linkToNodeId, true);
? validator.validateRuleSetNode(linkToNodeId, false)
: validator.validateFolderNode(linkToNodeId, false);
//The target node should have pre-existing rules to link to
if (!ruleService.hasRules(linkToNodeRef)) {

View File

@@ -26,29 +26,30 @@
package org.alfresco.rest.api.impl.rules;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.alfresco.rest.api.Nodes;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleExecution;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.util.collections.CollectionUtils;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.GUID;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,6 +59,7 @@ public class RulesImpl implements Rules
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
private static final String MUST_HAVE_AT_LEAST_ONE_ACTION = "A rule must have at least one action";
private ActionService actionService;
private RuleService ruleService;
private NodeValidator validator;
private RuleLoader ruleLoader;
@@ -130,6 +132,25 @@ public class RulesImpl implements Rules
ruleService.removeRule(folderNodeRef, rule);
}
@Override
public RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
final Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_RUN_ALL_RULES_ON_CHILDREN, eachSubFolderIncluded);
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_EXECUTE_INHERITED_RULES, true);
final ActionImpl action = new ActionImpl(null, GUID.generate(), ExecuteAllRulesActionExecuter.NAME);
action.setNodeRef(folderNodeRef);
action.setParameterValues(parameterValues);
ActionAccessRestriction.setActionContext(action, ActionAccessRestriction.V1_ACTION_CONTEXT);
actionService.executeAction(action, folderNodeRef, true, false);
return RuleExecution.builder()
.eachSubFolderIncluded(eachSubFolderIncluded)
.create();
}
private org.alfresco.service.cmr.rule.Rule mapToServiceModelAndValidateActions(Rule rule)
{
if (CollectionUtils.isEmpty(rule.getActions()))
@@ -141,6 +162,11 @@ public class RulesImpl implements Rules
return actionPermissionValidator.validateRulePermissions(serviceModelRule);
}
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;

View File

@@ -0,0 +1,171 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import static org.alfresco.model.ContentModel.TYPE_CATEGORY;
import static org.alfresco.model.ContentModel.TYPE_FOLDER;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.NODE_REF;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.PermissionService.WRITE;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter;
import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
import org.alfresco.repo.action.executer.ImporterActionExecuter;
import org.alfresco.repo.action.executer.LinkCategoryActionExecuter;
import org.alfresco.repo.action.executer.MoveActionExecuter;
import org.alfresco.repo.action.executer.SimpleWorkflowActionExecuter;
import org.alfresco.repo.action.executer.TransformActionExecuter;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
/**
* This class provides logic for validation of permissions for action parameters which reference node.
*/
public class ActionNodeParameterValidator implements ActionValidator
{
/**
* This list holds action parameter names which require only READ permission on a referenced node
* That means, all other parameters that reference nodes will require WRITE permission
*/
static final Map<String, List<String>> REQUIRE_READ_PERMISSION_PARAMS =
Map.of(LinkCategoryActionExecuter.NAME, List.of(LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE));
static final String NO_PROPER_PERMISSIONS_FOR_NODE = "No proper permissions for node: ";
static final String NOT_A_CATEGORY = "Node is not a category ";
static final String NOT_A_FOLDER = "Node is not a folder ";
private final Actions actions;
private final NamespaceService namespaceService;
private final Nodes nodes;
private final PermissionService permissionService;
public ActionNodeParameterValidator(Actions actions, NamespaceService namespaceService, Nodes nodes,
PermissionService permissionService)
{
this.actions = actions;
this.namespaceService = namespaceService;
this.nodes = nodes;
this.permissionService = permissionService;
}
/**
* Validates action parameters that reference nodes against access permissions for executing user.
*
* @param action Action to be validated
*/
@Override
public void validate(Action action)
{
final ActionDefinition actionDefinition = actions.getRuleActionDefinitionById(action.getActionDefinitionId());
final List<ActionDefinition.ParameterDefinition> nodeRefParams = actionDefinition.getParameterDefinitions().stream()
.filter(pd -> NODE_REF.toPrefixString(namespaceService).equals(pd.getType()))
.collect(Collectors.toList());
validateNodes(nodeRefParams, action);
}
/**
* @return List of action definitions applicable to this validator
*/
@Override
public List<String> getActionDefinitionIds()
{
return List.of(CopyActionExecuter.NAME, MoveActionExecuter.NAME, CheckOutActionExecuter.NAME, ImporterActionExecuter.NAME,
LinkCategoryActionExecuter.NAME, SimpleWorkflowActionExecuter.NAME, TransformActionExecuter.NAME,
ImageTransformActionExecuter.NAME);
}
@Override
public int getPriority()
{
return Integer.MIN_VALUE + 1;
}
private void validateNodes(final List<ActionDefinition.ParameterDefinition> nodeRefParamDefinitions,
final Action action)
{
if (MapUtils.isNotEmpty(action.getParams()))
{
nodeRefParamDefinitions.stream()
.filter(pd -> action.getParams().containsKey(pd.getName()))
.forEach(p -> {
final String nodeId = Objects.toString(action.getParams().get(p.getName()), Strings.EMPTY);
final NodeRef nodeRef = nodes.validateNode(nodeId);
validatePermission(action.getActionDefinitionId(), p.getName(), nodeRef);
validateType(action.getActionDefinitionId(), nodeRef);
});
}
}
private void validatePermission(final String actionDefinitionId, final String paramName, final NodeRef nodeRef)
{
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
{
throw new EntityNotFoundException(nodeRef.getId());
}
if (!REQUIRE_READ_PERMISSION_PARAMS.containsKey(actionDefinitionId) ||
REQUIRE_READ_PERMISSION_PARAMS.get(actionDefinitionId).stream().noneMatch(paramName::equals))
{
if (permissionService.hasPermission(nodeRef, WRITE) != ALLOWED)
{
throw new PermissionDeniedException(NO_PROPER_PERMISSIONS_FOR_NODE + nodeRef.getId());
}
}
}
private void validateType(final String actionDefinitionId, final NodeRef nodeRef)
{
if (!LinkCategoryActionExecuter.NAME.equals(actionDefinitionId))
{
if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_FOLDER), Collections.emptySet()))
{
throw new InvalidArgumentException(NOT_A_FOLDER + nodeRef.getId());
}
} else if (!nodes.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet()))
{
throw new InvalidArgumentException(NOT_A_CATEGORY + nodeRef.getId());
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
/**
* This class will validate all action types against action parameters definitions (mandatory parameters, parameter constraints)
*/
@Experimental
public class ActionParameterDefinitionValidator implements ActionValidator
{
static final String INVALID_PARAMETER_VALUE =
"Action parameter: %s has invalid value (%s). Look up possible values for constraint name %s";
static final String MISSING_PARAMETER = "Missing action's mandatory parameter: %s";
static final String MUST_NOT_CONTAIN_PARAMETER = "Action of definition id: %s must not contain parameter of name: %s";
static final String PARAMS_SHOULD_NOT_BE_EMPTY =
"Action parameters should not be null or empty for this action. See Action Definition for action of: %s";
static final String INVALID_ACTION_DEFINITION = "Invalid rule action definition requested %s";
static final String EMPTY_ACTION_DEFINITION = "Empty/null rule action definition id";
private final Actions actions;
public ActionParameterDefinitionValidator(Actions actions)
{
this.actions = actions;
}
/**
* Validates action against its parameters definitions (mandatory parameters, parameter constraints)
*
* @param action Action to be validated
*/
@Override
public void validate(Action action)
{
ActionDefinition actionDefinition;
final String actionDefinitionId = action.getActionDefinitionId();
if (Strings.isBlank(actionDefinitionId))
{
throw new InvalidArgumentException(EMPTY_ACTION_DEFINITION);
}
try
{
actionDefinition = actions.getRuleActionDefinitionById(actionDefinitionId);
} catch (NotFoundException e)
{
throw new InvalidArgumentException(String.format(INVALID_ACTION_DEFINITION, actionDefinitionId));
}
validateParametersSize(action.getParams(), actionDefinition);
final Map<String, Serializable> params = action.getParams();
if (MapUtils.isNotEmpty(params))
{
params.forEach((key, value) -> checkParameterShouldExist(key, actionDefinition));
getParameterDefinitions(actionDefinition).forEach(p -> validateParameterDefinitions(p, params));
}
}
/**
* This validator should be applied to all actions
*
* @return list of all defined action definition ids
*/
@Override
public List<String> getActionDefinitionIds()
{
return List.of(ALL_ACTIONS);
}
/**
* This validator should have highest priority and be executed first of all (thus minimal integer is returned here).
*
* @return minimal integer value
*/
@Override
public int getPriority()
{
return Integer.MIN_VALUE;
}
private void validateParametersSize(final Map<String, Serializable> params, final ActionDefinition actionDefinition)
{
final List<ActionDefinition.ParameterDefinition> parameterDefinitions = getParameterDefinitions(actionDefinition);
if (CollectionUtils.isNotEmpty(
parameterDefinitions.stream().filter(ActionDefinition.ParameterDefinition::isMandatory).collect(Collectors.toList())) &&
MapUtils.isEmpty(params))
{
throw new InvalidArgumentException(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinition.getName()));
}
}
private List<ActionDefinition.ParameterDefinition> getParameterDefinitions(ActionDefinition actionDefinition)
{
return actionDefinition.getParameterDefinitions() == null ? Collections.emptyList() : actionDefinition.getParameterDefinitions();
}
private void validateParameterDefinitions(final ActionDefinition.ParameterDefinition parameterDefinition,
final Map<String, Serializable> params)
{
final Serializable parameterValue = params.get(parameterDefinition.getName());
if (parameterDefinition.isMandatory() && parameterValue == null)
{
throw new InvalidArgumentException(String.format(MISSING_PARAMETER, parameterDefinition.getName()));
}
if (parameterDefinition.getParameterConstraintName() != null)
{
final ActionParameterConstraint actionConstraint =
actions.getActionConstraint(parameterDefinition.getParameterConstraintName());
if (parameterValue != null && actionConstraint.getConstraintValues().stream()
.noneMatch(constraintData -> constraintData.getValue().equals(Objects.toString(parameterValue, null))))
{
throw new InvalidArgumentException(String.format(INVALID_PARAMETER_VALUE, parameterDefinition.getName(), parameterValue,
actionConstraint.getConstraintName()));
}
}
}
private void checkParameterShouldExist(final String parameterName, final ActionDefinition actionDefinition)
{
if (getParameterDefinitions(actionDefinition).stream().noneMatch(pd -> parameterName.equals(pd.getName())))
{
throw new InvalidArgumentException(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinition.getName(), parameterName));
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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.api.model;
import java.util.List;
import org.alfresco.service.Experimental;
/**
* Representation of action parameter constraint.
* Helps to constraint the list of allowable values for an action parameter.
* When action parameter has constraints defined (@see ActionDefinition.ParameterDefinition#getParameterConstraintName())
* they will be listed here.
*
* @author mpichura
*/
@Experimental
public class ActionParameterConstraint
{
/**
* Constraint name.
*/
private String constraintName;
/**
* List of objects representing constraint values along with additional data
*/
private List<ConstraintData> constraintValues;
public List<ConstraintData> getConstraintValues()
{
return constraintValues;
}
public void setConstraintValues(List<ConstraintData> constraintValues)
{
this.constraintValues = constraintValues;
}
public String getConstraintName()
{
return constraintName;
}
public void setConstraintName(String constraintName)
{
this.constraintName = constraintName;
}
public static class ConstraintData
{
public ConstraintData(final String value, final String label)
{
this.value = value;
this.label = label;
}
/**
* Actual constraint value
*/
private String value;
/**
* A label associated to constraint's value
*/
private String label;
public String getValue()
{
return value;
}
public String getLabel()
{
return label;
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model.rules;
import java.util.Objects;
import org.alfresco.service.Experimental;
@Experimental
public class RuleExecution
{
private boolean eachSubFolderIncluded;
public boolean getIsEachSubFolderIncluded()
{
return eachSubFolderIncluded;
}
public void setIsEachSubFolderIncluded(boolean eachSubFolderIncluded)
{
this.eachSubFolderIncluded = eachSubFolderIncluded;
}
@Override
public String toString()
{
return "RuleExecution{" + "eachSubFolderIncluded=" + eachSubFolderIncluded + '}';
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
RuleExecution that = (RuleExecution) o;
return eachSubFolderIncluded == that.eachSubFolderIncluded;
}
@Override
public int hashCode()
{
return Objects.hash(eachSubFolderIncluded);
}
public static Builder builder()
{
return new Builder();
}
public static class Builder
{
private boolean eachSubFolderIncluded;
public Builder eachSubFolderIncluded(boolean eachSubFolderIncluded)
{
this.eachSubFolderIncluded = eachSubFolderIncluded;
return this;
}
public RuleExecution create()
{
final RuleExecution ruleExecution = new RuleExecution();
ruleExecution.setIsEachSubFolderIncluded(eachSubFolderIncluded);
return ruleExecution;
}
}
}

View File

@@ -45,6 +45,7 @@ public class RuleSet
private List<NodeRef> linkedToBy;
private Boolean isInherited;
private Boolean isLinkedTo;
private List<String> ruleIds;
public static RuleSet of(String id)
{
@@ -151,6 +152,16 @@ public class RuleSet
return isLinkedTo;
}
public List<String> getRuleIds()
{
return ruleIds;
}
public void setRuleIds(List<String> ruleIds)
{
this.ruleIds = ruleIds;
}
@Override
public String toString()
{
@@ -163,6 +174,7 @@ public class RuleSet
.add("linkedToBy='" + linkedToBy + "'")
.add("isInherited='" + isInherited + "'")
.add("isLinkedTo='" + isLinkedTo + "'")
.add("ruleIds='" + ruleIds + "'")
.toString()
+ '}';
}
@@ -181,13 +193,14 @@ public class RuleSet
&& Objects.equals(inheritedBy, ruleSet.inheritedBy)
&& Objects.equals(linkedToBy, ruleSet.linkedToBy)
&& Objects.equals(isInherited, ruleSet.isInherited)
&& Objects.equals(isLinkedTo, ruleSet.isLinkedTo);
&& Objects.equals(isLinkedTo, ruleSet.isLinkedTo)
&& Objects.equals(ruleIds, ruleSet.ruleIds);
}
@Override
public int hashCode()
{
return Objects.hash(id, owningFolder, inclusionType, inheritedBy, linkedToBy, isInherited, isLinkedTo);
return Objects.hash(id, owningFolder, inclusionType, inheritedBy, linkedToBy, isInherited, isLinkedTo, ruleIds);
}
public static Builder builder()
@@ -204,6 +217,7 @@ public class RuleSet
private List<NodeRef> linkedToBy;
private Boolean isInherited;
private Boolean isLinkedTo;
private List<String> ruleIds;
public Builder id(String id)
{
@@ -247,6 +261,12 @@ public class RuleSet
return this;
}
public Builder ruleIds(List<String> ruleIds)
{
this.ruleIds = ruleIds;
return this;
}
public RuleSet create()
{
final RuleSet ruleSet = new RuleSet();
@@ -257,6 +277,7 @@ public class RuleSet
ruleSet.setLinkedToBy(linkedToBy);
ruleSet.setIsInherited(isInherited);
ruleSet.setIsLinkedTo(isLinkedTo);
ruleSet.setRuleIds(ruleIds);
return ruleSet;
}
}

View File

@@ -0,0 +1,71 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.rules;
import java.util.List;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.rules.RuleExecution;
import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
@Experimental
@RelationshipResource(name = "rule-executions", entityResource = NodesEntityResource.class, title = "Executing rules")
public class NodeRuleExecutionsRelation implements RelationshipResourceAction.Create<RuleExecution>, InitializingBean
{
private final Rules rules;
public NodeRuleExecutionsRelation(Rules rules)
{
this.rules = rules;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "rules", this.rules);
}
/**
* Execute rules for given folder node.
*
* @param folderNodeId - the ID of a folder
* @param ruleExecutionParameters - rule execution parameters
* @param parameters - additional request parameters
* @return execution details
*/
@Override
public List<RuleExecution> create(String folderNodeId, List<RuleExecution> ruleExecutionParameters, Parameters parameters)
{
final RuleExecution ruleExecution = ruleExecutionParameters.stream().findFirst().orElse(new RuleExecution());
return List.of(rules.executeRules(folderNodeId, ruleExecution.getIsEachSubFolderIncluded()));
}
}

View File

@@ -24,7 +24,7 @@
* #L%
*/
package org.alfresco.rest.api.nodes;
package org.alfresco.rest.api.rules;
import java.util.List;
import java.util.stream.Collectors;
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSetLink;
import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.core.ResourceParameter;

View File

@@ -24,20 +24,18 @@
* #L%
*/
package org.alfresco.rest.api.nodes;
package org.alfresco.rest.api.rules;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
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.Paging;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
@@ -50,6 +48,7 @@ import org.springframework.beans.factory.InitializingBean;
@RelationshipResource(name = "rule-sets", entityResource = NodesEntityResource.class, title = "Folder node rule sets")
public class NodeRuleSetsRelation implements RelationshipResourceAction.Read<RuleSet>,
RelationshipResourceAction.ReadById<RuleSet>,
RelationshipResourceAction.Update<RuleSet>,
InitializingBean
{
private RuleSets ruleSets;
@@ -106,4 +105,20 @@ public class NodeRuleSetsRelation implements RelationshipResourceAction.Read<Rul
{
this.ruleSets = ruleSets;
}
/**
* Update a rule set, in particular this is useful for reordering rules in a rule set.
* <p>
* - PUT /nodes/{folderNodeId}/rule-sets/{ruleSetId}
*
* @param folderNodeId The id for the folder.
* @param ruleSet The updated rule set.
* @param parameters Contains information about which fields to include in the response.
* @return The updated rule set.
*/
@Override
public RuleSet update(String folderNodeId, RuleSet ruleSet, Parameters parameters)
{
return ruleSets.updateRuleSet(folderNodeId, ruleSet, parameters.getInclude());
}
}

View File

@@ -1,104 +1,105 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.nodes;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.RuleSettings;
import org.alfresco.rest.api.model.rules.RuleSetting;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* Folder node rule settings (rule inheritance).
*/
@Experimental
@RelationshipResource (name = "rule-settings", entityResource = NodesEntityResource.class, title = "Folder rule settings")
public class NodeRuleSettingsRelation implements RelationshipResourceAction.ReadById<RuleSetting>,
RelationshipResourceAction.Update<RuleSetting>,
InitializingBean
{
private RuleSettings ruleSettings;
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "ruleSettings", ruleSettings);
}
/**
* Get the given configuration value for the specified folder.
* <p>
* - GET /nodes/{folderId}/rule-settings/{ruleSettingKey}
*
* @param folderId The id of the folder.
* @param ruleSettingKey The setting to retrieve.
* @param parameters Unused.
* @return {@link RuleSetting} The current value of the setting.
*/
@WebApiDescription (
title = "Get a folder node rule setting",
description = "Returns the specified rule setting for the given folder",
successStatus = HttpServletResponse.SC_OK
)
@Override
public RuleSetting readById(String folderId, String ruleSettingKey, Parameters parameters) throws RelationshipResourceNotFoundException
{
return ruleSettings.getRuleSetting(folderId, ruleSettingKey);
}
/**
* Set the value of a rule setting for the specified folder.
* <p>
* PUT /nodes/{folderId}/rule-settings/{ruleSettingKey}
*
* @param folderId The id of the folder.
* @param ruleSetting The new value of the rule setting.
* @param parameters Unused.
* @return The updated rule setting.
*/
@WebApiDescription (
title = "Update folder node rule setting",
description = "Update a rule setting for given node",
successStatus = HttpServletResponse.SC_OK
)
@Override
public RuleSetting update(String folderId, RuleSetting ruleSetting, Parameters parameters)
{
return ruleSettings.setRuleSetting(folderId, ruleSetting);
}
public void setRuleSettings(RuleSettings ruleSettings)
{
this.ruleSettings = ruleSettings;
}
}
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.rules;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.RuleSettings;
import org.alfresco.rest.api.model.rules.RuleSetting;
import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* Folder node rule settings (rule inheritance).
*/
@Experimental
@RelationshipResource (name = "rule-settings", entityResource = NodesEntityResource.class, title = "Folder rule settings")
public class NodeRuleSettingsRelation implements RelationshipResourceAction.ReadById<RuleSetting>,
RelationshipResourceAction.Update<RuleSetting>,
InitializingBean
{
private RuleSettings ruleSettings;
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "ruleSettings", ruleSettings);
}
/**
* Get the given configuration value for the specified folder.
* <p>
* - GET /nodes/{folderId}/rule-settings/{ruleSettingKey}
*
* @param folderId The id of the folder.
* @param ruleSettingKey The setting to retrieve.
* @param parameters Unused.
* @return {@link RuleSetting} The current value of the setting.
*/
@WebApiDescription (
title = "Get a folder node rule setting",
description = "Returns the specified rule setting for the given folder",
successStatus = HttpServletResponse.SC_OK
)
@Override
public RuleSetting readById(String folderId, String ruleSettingKey, Parameters parameters) throws RelationshipResourceNotFoundException
{
return ruleSettings.getRuleSetting(folderId, ruleSettingKey);
}
/**
* Set the value of a rule setting for the specified folder.
* <p>
* PUT /nodes/{folderId}/rule-settings/{ruleSettingKey}
*
* @param folderId The id of the folder.
* @param ruleSetting The new value of the rule setting.
* @param parameters Unused.
* @return The updated rule setting.
*/
@WebApiDescription (
title = "Update folder node rule setting",
description = "Update a rule setting for given node",
successStatus = HttpServletResponse.SC_OK
)
@Override
public RuleSetting update(String folderId, RuleSetting ruleSetting, Parameters parameters)
{
return ruleSettings.setRuleSetting(folderId, ruleSetting);
}
public void setRuleSettings(RuleSettings ruleSettings)
{
this.ruleSettings = ruleSettings;
}
}

View File

@@ -24,7 +24,7 @@
* #L%
*/
package org.alfresco.rest.api.nodes;
package org.alfresco.rest.api.rules;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

View File

@@ -0,0 +1,29 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
@WebApi(name="alfresco", scope=Api.SCOPE.PRIVATE, version=1)
package org.alfresco.rest.api.rules;
import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.WebApi;

View File

@@ -34,7 +34,7 @@ public class EntityNotFoundException extends NotFoundException
{
private static final long serialVersionUID = -1198595000441207734L;
public static String DEFAULT_MESSAGE_ID = "framework.exception.EntityNotFound";
/**
* The entity id param will be shown in the default error message.
* @param entityId String
@@ -43,4 +43,20 @@ public class EntityNotFoundException extends NotFoundException
{
super(DEFAULT_MESSAGE_ID, new String[] {entityId});
}
/**
* The entity id param will be shown in the default error message.
*
* @param msgId The message template.
* @param parameters The message template parameters.
*/
public EntityNotFoundException(String msgId, String[] parameters)
{
super(msgId, parameters);
}
public EntityNotFoundException(String msgId, Throwable cause)
{
super(msgId, cause);
}
}

View File

@@ -53,4 +53,9 @@ public class NotFoundException extends ApiException
super(msgId, notFoundObjects);
}
public NotFoundException(String msgId, Throwable cause)
{
super(msgId, cause);
}
}

View File

@@ -155,6 +155,7 @@
<entry key="org.alfresco.rest.framework.core.exceptions.PermissionDeniedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_FORBIDDEN}" />
<entry key="org.alfresco.repo.security.authority.UnknownAuthorityException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_NOT_FOUND}" />
<entry key="org.alfresco.repo.security.permissions.AccessDeniedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_FORBIDDEN}" />
<entry key="org.alfresco.repo.action.access.ActionAccessException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_FORBIDDEN}" />
<entry key="org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_METHOD_NOT_ALLOWED}" />
<entry key="org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" />
<entry key="org.alfresco.service.cmr.lock.NodeLockedException" value="#{T(org.springframework.extensions.webscripts.Status).STATUS_CONFLICT}" />
@@ -566,6 +567,7 @@
<property name="namespaceService" ref="NamespaceService"/>
<property name="nodeService" ref="NodeService"/>
<property name="prefixResolver" ref="namespaceService"/>
<property name="actionParameterConverter" ref="actionParameterConverter"/>
</bean>
<bean id="Actions" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.alfresco.rest.api.Actions"/>
@@ -583,7 +585,23 @@
<bean class="org.alfresco.rest.api.actions.ActionExecutionsEntityResource">
<property name="actions" ref="Actions"/>
</bean>
<bean class="org.alfresco.rest.api.actions.ActionParameterConstraintsEntityResource">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<!-- action parameter validators start here -->
<bean id="actionParameterConstraintsValidator" class="org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator">
<constructor-arg name="actions" ref="Actions"/>
</bean>
<bean id="actionNodeParameterValidator" class="org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidator">
<constructor-arg name="actions" ref="Actions"/>
<constructor-arg name="namespaceService" ref="NamespaceService"/>
<constructor-arg name="nodes" ref="Nodes"/>
<constructor-arg name="permissionService" ref="PermissionService"/>
</bean>
<!-- action parameter validators end here-->
<bean id="Downloads" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.Downloads</value>
@@ -857,7 +875,7 @@
<property name="nodeService" ref="NodeService"/>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRulesRelation">
<bean class="org.alfresco.rest.api.rules.NodeRulesRelation">
<property name="rules" ref="Rules" />
</bean>
@@ -890,7 +908,7 @@
<property name="ruleMapper" ref="ruleMapper"/>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetsRelation">
<bean class="org.alfresco.rest.api.rules.NodeRuleSetsRelation">
<property name="ruleSets" ref="RuleSets" />
</bean>
@@ -898,6 +916,8 @@
<constructor-arg name="actionService" ref="ActionService"/>
<constructor-arg name="dictionaryService" ref="DictionaryService"/>
<constructor-arg name="namespaceService" ref="NamespaceService"/>
<constructor-arg name="permissionService" ref="PermissionService" />
<constructor-arg name="nodes" ref="Nodes"/>
</bean>
<bean id="actionPermissionValidator" class="org.alfresco.rest.api.impl.rules.ActionPermissionValidator">
@@ -905,6 +925,7 @@
</bean>
<bean id="rules" class="org.alfresco.rest.api.impl.rules.RulesImpl">
<property name="actionService" ref="ActionService"/>
<property name="validator" ref="nodeValidator"/>
<property name="ruleService" ref="RuleService" />
<property name="ruleLoader" ref="ruleLoader"/>
@@ -922,10 +943,14 @@
</property>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetLinksRelation">
<bean class="org.alfresco.rest.api.rules.NodeRuleSetLinksRelation">
<constructor-arg name="ruleSets" ref="RuleSets" />
</bean>
<bean class="org.alfresco.rest.api.rules.NodeRuleExecutionsRelation">
<constructor-arg name="rules" ref="Rules" />
</bean>
<bean id="ruleSettings" class="org.alfresco.rest.api.impl.rules.RuleSettingsImpl">
<property name="validator" ref="nodeValidator" />
<property name="nodeService" ref="NodeService" />
@@ -941,7 +966,7 @@
</property>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSettingsRelation">
<bean class="org.alfresco.rest.api.rules.NodeRuleSettingsRelation">
<property name="ruleSettings" ref="RuleSettings" />
</bean>
@@ -955,6 +980,12 @@
<bean id="actionMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleActionModelMapper">
<constructor-arg name="parameterConverter" ref="actionParameterConverter"/>
<constructor-arg name="actionValidators">
<list>
<ref bean="actionParameterConstraintsValidator"/>
<ref bean="actionNodeParameterValidator"/>
</list>
</constructor-arg>
</bean>
<bean id="ruleMapper" class="org.alfresco.rest.api.impl.mapper.rules.RestRuleModelMapper">

View File

@@ -8,6 +8,7 @@
<property name="enabled" value="${system.webdav.servlet.enabled}" />
<property name="storeName" value="${system.webdav.storeName}" />
<property name="rootPath" value="${system.webdav.rootPath}" />
<property name="allowInsecurePOSTMethod" value="${system.webdav.allowInsecurePOSTMethod}" />
</bean>
<bean id="webDAVLockService" class="org.alfresco.repo.webdav.WebDAVLockServiceImpl">

View File

@@ -3,12 +3,13 @@ function main()
// Get the args
var siteShortName = url.templateArgs.shortname,
site = siteService.getSite(siteShortName),
filter = ((args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "" )+ " [hint:useCQ]",
maxResults = (args.maxResults == null) ? 10 : parseInt(args.maxResults, 10),
authorityType = args.authorityType,
zone = args.zone,
sortBy = args.sortBy,
sortAsc = args.dir != "desc";
var filter;
if (authorityType != null)
@@ -28,6 +29,7 @@ function main()
if (authorityType == null || authorityType == "USER")
{
filter = ((args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "" )+ " [hint:useCQ]";
// Get the collection of people
peopleFound = sortBy != null ? people.getPeople(filter, maxResults, sortBy, sortAsc) : people.getPeople(filter, maxResults);
@@ -67,6 +69,7 @@ function main()
if (authorityType == null || authorityType == "GROUP")
{
filter = (args.filter != null) ? args.filter : (args.shortNameFilter != null) ? args.shortNameFilter : "";
// Get the collection of groups
paging = utils.createPaging(maxResults, -1);
groupsFound = groups.getGroupsInZone(filter, zone, paging, "displayName");
@@ -96,4 +99,4 @@ function contains(arr, value) {
return false;
}
main();
main();

View File

@@ -0,0 +1,82 @@
<#import "/org/springframework/extensions/webscripts/webscripts.lib.html.ftl" as wsLib/>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<@wsLib.head>${msg("alfresco.index.title")}</@wsLib.head>
<body>
<div>
<@wsLib.indexheader>Web Scripts Home</@wsLib.indexheader>
<#if failures?size &gt; 0>
<br/>
<table>
<tr><td><a href="${url.serviceContext}/index/failures">(+${failures?size} failed)</td></tr>
</table>
</#if>
<br>
<@wsLib.onlinedoc/>
<br/>
<span class="mainSubTitle">Index</span>
<#if rootfamily.children?size &gt; 0>
<table>
<#list rootfamily.children as childpath>
<tr><td><a href="${url.serviceContext}/index/family${childpath.path}">Browse '${childpath.name}' Web Scripts</a></td></tr>
</#list>
</table>
<br/>
</#if>
<table>
<tr><td><a href="${url.serviceContext}/index/all">Browse all Web Scripts</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/uri/">Browse by Web Script URI</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/package/">Browse by Web Script Package</a></td></tr>
<tr><td><a href="${url.serviceContext}/index/lifecycle/">Browse by Web Script Lifecycle</a></td></tr>
</table>
<br/>
<br/>
<span class="mainSubTitle">Maintenance</span>
<form id="refresh" action="${url.serviceContext}${url.match}" method="post">
<input type="hidden" name="reset" value="on"/>
<table>
<#if failures?size &gt; 0>
<tr><td><a href="${url.serviceContext}/index/failures">Browse failed Web Scripts</a></td></tr>
</#if>
<tr><td><a href="${url.serviceContext}/api/javascript/debugger">Alfresco Javascript Debugger</a></td></tr>
</table>
<br/>
<table>
<tr><td><input type="submit" name="submit" value="Refresh Web Scripts"/></td></tr>
</table>
</form>
</div>
<#assign CSRF=(config.scoped["CSRFPolicy"]["filter"].getChildren("rule")?size != 0)!false>
<#if CSRF>
<script type="text/javascript">
function addCsrfTokenToRefreshForm() {
const properties = {};
<#if config.scoped["CSRFPolicy"]["properties"]??>
<#assign csrfProperties = (config.scoped["CSRFPolicy"]["properties"].children)![]>
<#list csrfProperties as p>
properties["${p.name?js_string}"] = "${(p.value!"")?js_string}";
</#list>
</#if>
function substitute(str) {
for (const prop in properties) {
str = str.replace("{" + prop + "}", properties[prop]);
}
return str;
}
const csrfCookieName = substitute("${config.scoped["CSRFPolicy"]["client"].getChildValue("cookie")!""}");
const csrfParamName = substitute("${config.scoped["CSRFPolicy"]["client"].getChildValue("parameter")!""}");
const matchingCookies = document.cookie.match(new RegExp("(?:^|; )" + csrfCookieName + "=([^;]*)"));
if (matchingCookies) {
const csrfToken = decodeURIComponent(matchingCookies[1]).replace(/"/g, '');
const form = document.getElementById('refresh');
const originalAction = form.attributes.action.value;
form.attributes.action.value = originalAction + (originalAction.lastIndexOf('?') === -1 ? "?" : "&") + csrfParamName + "=" + encodeURIComponent(csrfToken);
}
}
window.addEventListener('load', addCsrfTokenToRefreshForm, false);
</script>
</#if>
</body>
</html>

View File

@@ -99,6 +99,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.webdav.WebDAVMethodTest.class,
org.alfresco.repo.webdav.PutMethodTest.class,
org.alfresco.repo.webdav.WebDAVonContentUpdateTest.class,
org.alfresco.repo.webdav.WebDAVInsecurePostMethodTest.class,
// [classpath:test-rest-context.xml]
org.alfresco.rest.framework.tests.core.ExceptionResolverTests.class,

View File

@@ -0,0 +1,131 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.webdav;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Hashtable;
import org.alfresco.repo.webdav.WebDAVServlet.WebDAVInitParameters;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Tests for the allowInsecurePOSTMethod flag.
*
* @see WebDAVInitParameters
* @author Aleksandra Onych
*/
@RunWith(MockitoJUnitRunner.class)
public class WebDAVInsecurePostMethodTest
{
private WebDAVServlet davServlet;
private @Mock WebDAVInitParameters webDAVInitParameters;
private @Mock HttpServletRequest request;
private @Mock HttpServletResponse response;
private @Mock Hashtable<String,Class<? extends WebDAVMethod>> davMethods;
@Before
public void setUp()
{
davServlet = new WebDAVServlet();
ReflectionTestUtils.setField(davServlet, "initParams", webDAVInitParameters);
ReflectionTestUtils.setField(davServlet, "m_davMethods", davMethods);
when(webDAVInitParameters.getEnabled()).thenReturn(true);
}
@Test
public void shouldReturn405StatusWhenPostMethodIsNotAllowed() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_POST);
when(webDAVInitParameters.allowInsecurePOSTMethod()).thenReturn(false);
davServlet.service(request, response);
verify(response).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusWhenPostMethodIsAllowed() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_POST);
when(webDAVInitParameters.allowInsecurePOSTMethod()).thenReturn(true);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForPutMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_PUT);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForGetMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_GET);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
@Test
public void shouldNotReturn405StatusForDeleteMethod() throws ServletException, IOException
{
prepareRequest(WebDAV.METHOD_DELETE);
davServlet.service(request, response);
verify(response, never()).sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
private void prepareRequest(String requestMethodName)
{
doReturn(PutMethod.class).when(davMethods).get(requestMethodName);
when(request.getMethod()).thenReturn(requestMethodName);
}
}

View File

@@ -36,7 +36,10 @@ import org.alfresco.rest.api.impl.rules.NodeValidatorTest;
import org.alfresco.rest.api.impl.rules.RuleLoaderTest;
import org.alfresco.rest.api.impl.rules.RuleSetsImplTest;
import org.alfresco.rest.api.impl.rules.RulesImplTest;
import org.alfresco.rest.api.nodes.NodeRulesRelationTest;
import org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidatorTest;
import org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidatorTest;
import org.alfresco.rest.api.rules.NodeRuleSetsRelationTest;
import org.alfresco.rest.api.rules.NodeRulesRelationTest;
import org.alfresco.service.Experimental;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -45,12 +48,15 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
NodeRulesRelationTest.class,
NodeRuleSetsRelationTest.class,
RulesImplTest.class,
RuleSetsImplTest.class,
NodeValidatorTest.class,
RuleLoaderTest.class,
ActionParameterConverterTest.class,
ActionPermissionValidatorTest.class,
ActionParameterDefinitionValidatorTest.class,
ActionNodeParameterValidatorTest.class,
RestRuleSimpleConditionModelMapperTest.class,
RestRuleCompositeConditionModelMapperTest.class,
RestRuleActionModelMapperTest.class,

View File

@@ -0,0 +1,66 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionConstraintsEntityResourceTest
{
@Mock
private Actions actionsMock;
@Mock
private Parameters parametersMock;
@InjectMocks
private ActionConstraintsEntityResource objectUnderTest;
@Test
public void testReadById() {
final String name = "name";
final ActionParameterConstraint dummyConstraint = new ActionParameterConstraint();
given(actionsMock.getActionConstraint(name)).willReturn(dummyConstraint);
//when
ActionParameterConstraint result = objectUnderTest.readById(name, parametersMock);
then(actionsMock).should().getActionConstraint(name);
then(actionsMock).shouldHaveNoMoreInteractions();
assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(dummyConstraint);
}
}

View File

@@ -0,0 +1,66 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.actions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionParameterConstraintsEntityResourceTest
{
@Mock
private Actions actionsMock;
@Mock
private Parameters parametersMock;
@InjectMocks
private ActionParameterConstraintsEntityResource objectUnderTest;
@Test
public void testReadById() {
final String name = "name";
final ActionParameterConstraint dummyConstraint = new ActionParameterConstraint();
given(actionsMock.getActionConstraint(name)).willReturn(dummyConstraint);
//when
ActionParameterConstraint result = objectUnderTest.readById(name, parametersMock);
then(actionsMock).should().getActionConstraint(name);
then(actionsMock).shouldHaveNoMoreInteractions();
assertThat(result).isNotNull().usingRecursiveComparison().isEqualTo(dummyConstraint);
}
}

View File

@@ -0,0 +1,165 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import static org.alfresco.rest.api.impl.ActionsImpl.CONSTRAINT_NOT_EXISTS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.Map;
import org.alfresco.repo.action.constraint.FolderContentsParameterConstraint;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.ActionParameterConstraint;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.ParameterConstraint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionsImplTest
{
private static final String NAME = "name";
private static final String CONSTRAINT = "constraint";
private static final String LABEL = "label";
private static final String DISPLAY = "display ";
@Mock
private ActionService actionServiceMock;
@Mock
private Parameters parametersMock;
@Mock
private ActionParameterConverter parameterConverterMock;
@InjectMocks
private ActionsImpl objectUnderTest;
@Test
public void testGetSingleActionConstraint()
{
final String name = "name";
final String value = CONSTRAINT;
final String label = LABEL;
final Map<String, String> values = Map.of(value, label);
final ParameterConstraint testConstraint = createTestConstraint(name, values);
given(actionServiceMock.getParameterConstraint(name)).willReturn(testConstraint);
//when
final ActionParameterConstraint actualConstraint = objectUnderTest.getActionConstraint(name);
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
assertThat(actualConstraint).isNotNull();
assertThat(actualConstraint.getConstraintName()).isEqualTo(testConstraint.getName());
ActionParameterConstraint.ConstraintData expectedConstraintData = new ActionParameterConstraint.ConstraintData(value, label);
assertThat(actualConstraint.getConstraintValues()).isNotNull().hasSize(1);
ActionParameterConstraint.ConstraintData actualConstraintData = actualConstraint.getConstraintValues().get(0);
assertThat(actualConstraintData).usingRecursiveComparison().isEqualTo(expectedConstraintData);
}
@Test
public void testGetSingleActionNodeConstraint()
{
final String name = "name1";
final String dummyNodeId = "dummy-node-id";
final String value = "workspace://DummyStore/" + dummyNodeId;
final Map<String, String> values = Map.of(value, LABEL);
final FolderContentsParameterConstraint testConstraint = mock(FolderContentsParameterConstraint.class);
given(testConstraint.getName()).willReturn(name);
given(testConstraint.getValues()).willReturn(values);
given(actionServiceMock.getParameterConstraint(name)).willReturn(testConstraint);
given(parameterConverterMock.convertParamFromServiceModel(any())).willReturn(dummyNodeId);
//when
final ActionParameterConstraint actualConstraint = objectUnderTest.getActionConstraint(name);
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
assertThat(actualConstraint).isNotNull();
assertThat(actualConstraint.getConstraintName()).isEqualTo(testConstraint.getName());
ActionParameterConstraint.ConstraintData expectedConstraintData = new ActionParameterConstraint.ConstraintData(dummyNodeId, LABEL);
assertThat(actualConstraint.getConstraintValues()).isNotNull().hasSize(1);
ActionParameterConstraint.ConstraintData actualConstraintData = actualConstraint.getConstraintValues().get(0);
assertThat(actualConstraintData).usingRecursiveComparison().isEqualTo(expectedConstraintData);
}
@Test
public void testGetActionConstraintsWithNameFilterNonExistingConstraint()
{
final String name = "name";
given(actionServiceMock.getParameterConstraint(name)).willReturn(null);
//when
assertThatExceptionOfType(NotFoundException.class).isThrownBy(() -> objectUnderTest.getActionConstraint(name))
.withMessageContaining(String.format(CONSTRAINT_NOT_EXISTS, name));
then(parametersMock).shouldHaveNoInteractions();
then(actionServiceMock).should().getParameterConstraint(name);
then(actionServiceMock).shouldHaveNoMoreInteractions();
}
private ParameterConstraint createTestConstraint(final String name, final Map<String, String> values)
{
return new ParameterConstraint()
{
@Override
public String getName()
{
return name;
}
@Override
public boolean isValidValue(String value)
{
return true;
}
@Override
public String getValueDisplayLabel(String value)
{
return DISPLAY + name;
}
@Override
public Map<String, String> getAllowableValues()
{
return values;
}
};
}
}

View File

@@ -26,6 +26,8 @@
package org.alfresco.rest.api.impl.mapper.rules;
import static java.util.Collections.emptyMap;
import static org.alfresco.repo.action.access.ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME;
import static org.alfresco.repo.action.executer.SetPropertyValueActionExecuter.PARAM_PROPERTY;
import static org.alfresco.repo.action.executer.SetPropertyValueActionExecuter.PARAM_VALUE;
@@ -41,11 +43,14 @@ import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.rest.api.actions.ActionValidator;
import org.alfresco.rest.api.impl.rules.ActionParameterConverter;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
@@ -63,10 +68,16 @@ public class RestRuleActionModelMapperTest
@Mock
private ActionParameterConverter parameterConverter;
@Mock
private ActionValidator sampleValidatorMock;
@InjectMocks
private RestRuleActionModelMapper objectUnderTest;
@Before
public void setUp() {
objectUnderTest = new RestRuleActionModelMapper(parameterConverter, List.of(sampleValidatorMock));
}
@Test
public void testToRestModel()
{
@@ -89,7 +100,7 @@ public class RestRuleActionModelMapperTest
public void testToRestModelWithNullValues()
{
final org.alfresco.service.cmr.action.Action actionServiceModel = new ActionImpl(null, null, null);
final Action expectedAction = Action.builder().params(Collections.emptyMap()).create();
final Action expectedAction = Action.builder().params(emptyMap()).create();
//when
final Action actualAction = objectUnderTest.toRestModel(actionServiceModel);
@@ -122,4 +133,16 @@ public class RestRuleActionModelMapperTest
assertThat(serviceModelAction).isNull();
}
@Test
public void testToServiceModelWithNullParams()
{
final Action action = Action.builder().actionDefinitionId(ACTION_DEFINITION_NAME).params(null).create();
final List<Action> actions = List.of(action);
//when
final org.alfresco.service.cmr.action.Action serviceModelAction = objectUnderTest.toServiceModel(actions);
then(parameterConverter).should().getConvertedParams(emptyMap(), ACTION_DEFINITION_NAME);
then(parameterConverter).shouldHaveNoMoreInteractions();
assertThat(serviceModelAction).isNotNull();
}
}

View File

@@ -26,8 +26,12 @@
package org.alfresco.rest.api.impl.rules;
import static org.alfresco.repo.action.executer.CopyActionExecuter.PARAM_DESTINATION_FOLDER;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.AccessStatus.DENIED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -40,6 +44,7 @@ import java.io.Serializable;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
import org.alfresco.repo.action.executer.CheckInActionExecuter;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
@@ -50,6 +55,9 @@ import org.alfresco.repo.action.executer.RemoveFeaturesActionExecuter;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.repo.action.executer.SetPropertyValueActionExecuter;
import org.alfresco.repo.action.executer.SimpleWorkflowActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionDefinition;
@@ -58,8 +66,11 @@ import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.logging.log4j.util.Strings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
@@ -81,8 +92,10 @@ public class ActionParameterConverterTest
private static final String IDENTIFIER = "identifier";
private static final String IDENTIFIER_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + IDENTIFIER;
private static final String DUMMY_FOLDER_NODE_ID = "dummy-folder-node";
private static final String DUMMY_SCRIPT_NODE_ID = "dummy-script-ref";
private static final String DUMMY_FOLDER_NODE_ID = "dummy://folder/node";
private static final NodeRef DUMMY_FOLDER_NODE = new NodeRef(DUMMY_FOLDER_NODE_ID);
private static final String DUMMY_SCRIPT_NODE_ID = "dummy://script/ref";
private static final NodeRef DUMMY_SCRIPT_NODE = new NodeRef(DUMMY_SCRIPT_NODE_ID);
@Mock
private DictionaryService dictionaryService;
@@ -90,6 +103,10 @@ public class ActionParameterConverterTest
private ActionService actionService;
@Mock
private NamespaceService namespaceService;
@Mock
private PermissionService permissionService;
@Mock
private Nodes nodes;
@Mock
private ActionDefinition actionDefinition;
@@ -109,6 +126,15 @@ public class ActionParameterConverterTest
@InjectMocks
private ActionParameterConverter objectUnderTest;
@Before
public void setUp()
{
given(nodes.validateOrLookupNode(DUMMY_FOLDER_NODE_ID, null)).willReturn(DUMMY_FOLDER_NODE);
given(nodes.validateOrLookupNode(DUMMY_SCRIPT_NODE_ID, null)).willReturn(DUMMY_SCRIPT_NODE);
given(permissionService.hasReadPermission(DUMMY_FOLDER_NODE)).willReturn(ALLOWED);
given(permissionService.hasReadPermission(DUMMY_SCRIPT_NODE)).willReturn(ALLOWED);
}
@Test
public void testAddAspectConversion()
{
@@ -146,7 +172,7 @@ public class ActionParameterConverterTest
public void testCopyConversion()
{
final String name = CopyActionExecuter.NAME;
final String destinationFolderKey = CopyActionExecuter.PARAM_DESTINATION_FOLDER;
final String destinationFolderKey = PARAM_DESTINATION_FOLDER;
final String deepCopyKey = CopyActionExecuter.PARAM_DEEP_COPY;
final Map<String, Serializable> params = Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID, deepCopyKey, true);
@@ -177,8 +203,7 @@ public class ActionParameterConverterTest
final Serializable convertedCopyParam = convertedParams.get(destinationFolderKey);
assertTrue(convertedCopyParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedCopyParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedCopyParam);
final Serializable convertedDeepCopyParam = convertedParams.get(deepCopyKey);
assertThat(convertedDeepCopyParam instanceof Boolean).isTrue();
assertTrue(((Boolean) convertedDeepCopyParam));
@@ -211,8 +236,7 @@ public class ActionParameterConverterTest
final Serializable convertedCopyParam = convertedParams.get(executeScriptKey);
assertTrue(convertedCopyParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
assertEquals(DUMMY_SCRIPT_NODE_ID, ((NodeRef) convertedCopyParam).getId());
assertEquals(DUMMY_SCRIPT_NODE, convertedCopyParam);
}
@Test
@@ -242,8 +266,7 @@ public class ActionParameterConverterTest
final Serializable convertedCopyParam = convertedParams.get(destinationFolderKey);
assertTrue(convertedCopyParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedCopyParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedCopyParam);
}
@Test
@@ -330,8 +353,7 @@ public class ActionParameterConverterTest
final Serializable convertedDestinationParam = convertedParams.get(destinationFolderKey);
assertTrue(convertedDestinationParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedDestinationParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedDestinationParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedDestinationParam);
final Serializable convertedAssocNameParam = convertedParams.get(assocNameKey);
assertTrue(convertedAssocNameParam instanceof QName);
assertEquals(CHECKOUT, ((QName) convertedAssocNameParam).getLocalName());
@@ -385,8 +407,7 @@ public class ActionParameterConverterTest
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedCatValueParam).getNamespaceURI());
final Serializable convertedDestinationParam = convertedParams.get(categoryValueKey);
assertTrue(convertedDestinationParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedDestinationParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedDestinationParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedDestinationParam);
}
@Test
@@ -484,12 +505,10 @@ public class ActionParameterConverterTest
assertEquals(reject, convertedRejectStepParam);
final Serializable convertedApproveFolderParam = convertedParams.get(approveFolderKey);
assertTrue(convertedApproveFolderParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedApproveFolderParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedApproveFolderParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedApproveFolderParam);
final Serializable convertedRejectFolderParam = convertedParams.get(rejectFolderKey);
assertTrue(convertedRejectFolderParam instanceof NodeRef);
assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedRejectFolderParam).getStoreRef());
assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedRejectFolderParam).getId());
assertEquals(DUMMY_FOLDER_NODE, convertedRejectFolderParam);
final Serializable convertedApproveMoveParam = convertedParams.get(approveMoveKey);
assertTrue(convertedApproveMoveParam instanceof Boolean);
assertTrue((Boolean) convertedApproveMoveParam);
@@ -555,6 +574,66 @@ public class ActionParameterConverterTest
assertEquals(propType, convertedPropTypeParam);
}
@Test
public void testNonExistentNodeParam()
{
final String name = CopyActionExecuter.NAME;
final Map<String, Serializable> params = Map.of(PARAM_DESTINATION_FOLDER, "non://existent/node");
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(PARAM_DESTINATION_FOLDER)).willReturn(actionDefinitionParam1);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(nodeRef);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.getConvertedParams(params, name));
}
@Test
public void testNoReadPermissionForNodeParam()
{
final String name = CopyActionExecuter.NAME;
String permissionDeniedNodeId = "permission://denied/node";
final Map<String, Serializable> params = Map.of(PARAM_DESTINATION_FOLDER, permissionDeniedNodeId);
NodeRef permissionDeniedNode = new NodeRef(permissionDeniedNodeId);
given(nodes.validateOrLookupNode(permissionDeniedNodeId, null)).willReturn(permissionDeniedNode);
given(permissionService.hasReadPermission(permissionDeniedNode)).willReturn(DENIED);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(PARAM_DESTINATION_FOLDER)).willReturn(actionDefinitionParam1);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(nodeRef);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.getConvertedParams(params, name));
}
@Test
public void testNullParamValue()
{
final String name = CheckOutActionExecuter.NAME;
final String destinationFolderKey = CheckOutActionExecuter.PARAM_DESTINATION_FOLDER;
final String assocNameKey = CheckOutActionExecuter.PARAM_ASSOC_QNAME;
final String assocTypeKey = CheckOutActionExecuter.PARAM_ASSOC_TYPE_QNAME;
final Map<String, Serializable> params =
Map.of(destinationFolderKey, Strings.EMPTY, assocNameKey, Strings.EMPTY, assocTypeKey, Strings.EMPTY);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
//when
assertThrows(InvalidArgumentException.class, () ->objectUnderTest.getConvertedParams(params, name));
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).shouldHaveNoInteractions();
then(dictionaryService).shouldHaveNoInteractions();
then(namespaceService).shouldHaveNoInteractions();
}
@Test
public void testInvalidActionDefinitionConversion() {
final String invalidName = "dummy-definition";

View File

@@ -90,6 +90,7 @@ public class RuleSetLoaderTest extends TestCase
given(nodeServiceMock.getParentAssocs(RULE_SET_NODE)).willReturn(List.of(ruleSetAssociationMock, linkAssociationMock));
given(ruleServiceMock.getFoldersInheritingRuleSet(eq(RULE_SET_NODE), anyInt())).willReturn(List.of(INHERITING_FOLDER));
given(ruleServiceMock.getFoldersLinkingToRuleSet(eq(RULE_SET_NODE), anyInt())).willReturn(List.of(LINKING_FOLDER));
}
@Test

View File

@@ -27,6 +27,7 @@ package org.alfresco.rest.api.impl.rules;
import static java.util.Collections.emptyList;
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.RULE_IDS;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -41,12 +42,12 @@ import java.util.List;
import junit.framework.TestCase;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.repo.rule.RuntimeRuleService;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.AspectMissingException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -98,7 +99,7 @@ public class RuleSetsImplTest extends TestCase
MockitoAnnotations.openMocks(this);
given(nodeValidatorMock.validateFolderNode(eq(LINK_TO_NODE_ID), anyBoolean())).willReturn(LINK_TO_NODE);
given(nodeValidatorMock.validateRuleSetNode(LINK_TO_NODE_ID,true)).willReturn(LINK_TO_NODE);
given(nodeValidatorMock.validateRuleSetNode(LINK_TO_NODE_ID,false)).willReturn(LINK_TO_NODE);
given(nodeValidatorMock.validateFolderNode(eq(FOLDER_ID), anyBoolean())).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
@@ -146,6 +147,34 @@ public class RuleSetsImplTest extends TestCase
assertEquals(PAGING, actual.getPaging());
}
@Test
public void testOnlyGetPermittedRuleSets()
{
// Simulate a private folder with a rule set that the current user can't access.
NodeRef privateFolder = new NodeRef("private://folder/");
NodeRef privateRuleSetNode = new NodeRef("private://rule/set/node/");
given(ruleServiceMock.getRuleSetNode(privateFolder)).willReturn(privateRuleSetNode);
given(ruleServiceMock.getNodesSupplyingRuleSets(FOLDER_NODE)).willReturn(List.of(FOLDER_NODE, privateFolder));
given(ruleSetLoaderMock.loadRuleSet(eq(privateRuleSetNode), any(NodeRef.class), any(List.class)))
.willThrow(new AccessDeniedException("Cannot access private rule set."));
// Call the method under test.
CollectionWithPagingInfo<RuleSet> actual = ruleSets.getRuleSets(FOLDER_ID, INCLUDES, PAGING);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().getNodesSupplyingRuleSets(FOLDER_NODE);
then(ruleServiceMock).should().getRuleSetNode(FOLDER_NODE);
then(ruleServiceMock).should().getRuleSetNode(privateFolder);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
// Check we only get the accessible rule set back.
Collection<RuleSet> expected = List.of(ruleSetMock);
assertEquals(expected, actual.getCollection());
assertEquals(PAGING, actual.getPaging());
}
/** Check that a folder with a parent and grandparent can inherit rule sets from the grandparent, even if the parent has no rules. */
@Test
public void testGetInheritedRuleSets()
@@ -252,7 +281,7 @@ public class RuleSetsImplTest extends TestCase
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID,true);
then(nodeValidatorMock).should().isRuleSetNode(LINK_TO_NODE_ID);
then(nodeValidatorMock).should().validateRuleSetNode(LINK_TO_NODE_ID,true);
then(nodeValidatorMock).should().validateRuleSetNode(LINK_TO_NODE_ID,false);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
then(ruleServiceMock).should().hasRules(FOLDER_NODE);
@@ -329,4 +358,126 @@ public class RuleSetsImplTest extends TestCase
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(nodeServiceMock).shouldHaveNoInteractions();
}
@Test
public void testUpdateRuleSet()
{
given(ruleSetMock.getId()).willReturn(RULE_SET_ID);
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
RuleSet ruleSetResponse = mock(RuleSet.class);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, emptyList())).willReturn(ruleSetResponse);
//when
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, ruleSetMock, emptyList());
assertEquals("Unexpected rule set returned.", ruleSetResponse, ruleSet);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE);
then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE, FOLDER_NODE, emptyList());
}
/** Simulate rules being reordered from [RuleA, RuleB] to [RuleB, RuleA]. */
@Test
public void testUpdateRuleSet_reorderRules()
{
List<String> dbOrder = List.of("RuleA", "RuleB");
List<String> newOrder = List.of("RuleB", "RuleA");
List<String> includes = List.of(RULE_IDS);
RuleSet dbRuleSet = mock(RuleSet.class);
RuleSet requestRuleSet = mock(RuleSet.class);
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
//when
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes);
assertEquals("Unexpected rule set returned.", dbRuleSet, ruleSet);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE);
then(ruleSetLoaderMock).should().loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes);
then(dbRuleSet).should().setRuleIds(newOrder);
}
/** Check that we can't remove a rule by updating the rule set. */
@Test
public void testUpdateRuleSet_tryToChangeSetOfRuleIds()
{
List<String> dbOrder = List.of("RuleA", "RuleB");
List<String> newOrder = List.of("RuleA");
List<String> includes = List.of(RULE_IDS);
RuleSet dbRuleSet = mock(RuleSet.class);
RuleSet requestRuleSet = mock(RuleSet.class);
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes)
);
}
/** Check that we can't include a rule twice in a rule set. */
@Test
public void testUpdateRuleSet_DuplicateRuleId()
{
List<String> dbOrder = List.of("RuleA", "RuleB");
List<String> newOrder = List.of("RuleA", "RuleB", "RuleA");
List<String> includes = List.of(RULE_IDS);
RuleSet dbRuleSet = mock(RuleSet.class);
RuleSet requestRuleSet = mock(RuleSet.class);
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes)
);
}
/** Check that we can update the rule ids without returning them. */
@Test
public void testUpdateRuleSet_dontIncludeRuleIds()
{
List<String> dbOrder = List.of("RuleA", "RuleB");
List<String> newOrder = List.of("RuleB", "RuleA");
List<String> includes = emptyList();
RuleSet dbRuleSet = mock(RuleSet.class);
RuleSet requestRuleSet = mock(RuleSet.class);
given(requestRuleSet.getId()).willReturn(RULE_SET_ID);
given(requestRuleSet.getRuleIds()).willReturn(newOrder);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, includes)).willReturn(dbRuleSet);
given(ruleSetLoaderMock.loadRuleIds(FOLDER_NODE)).willReturn(dbOrder);
given(nodeValidatorMock.validateFolderNode(FOLDER_ID, false)).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
//when
RuleSet ruleSet = ruleSets.updateRuleSet(FOLDER_ID, requestRuleSet, includes);
// Expect the DB rule set to be returned, but no extra fields to be populated.
assertEquals("Unexpected rule set returned.", dbRuleSet, ruleSet);
then(dbRuleSet).shouldHaveNoInteractions();
}
}

View File

@@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
@@ -40,13 +41,18 @@ import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import junit.framework.TestCase;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleExecution;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
@@ -54,12 +60,14 @@ import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundE
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -77,10 +85,14 @@ public class RulesImplTest extends TestCase
private static final NodeRef RULE_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
private static final Paging PAGING = Paging.DEFAULT;
private static final List<String> INCLUDE = emptyList();
private static final boolean INCLUDE_SUB_FOLDERS = true;
private static final boolean EXECUTE_INHERITED_RULES = true;
@Mock
private Nodes nodesMock;
@Mock
private ActionService actionServiceMock;
@Mock
private RestModelMapper<Rule, org.alfresco.service.cmr.rule.Rule> ruleMapper;
@Mock
private NodeValidator nodeValidatorMock;
@@ -618,6 +630,36 @@ public class RulesImplTest extends TestCase
}
}
@Test
public void testExecuteRule()
{
// when
final RuleExecution actualRuleExecution = rules.executeRules(FOLDER_NODE_ID, INCLUDE_SUB_FOLDERS);
final RuleExecution expectedRuleExecution = RuleExecution.builder().eachSubFolderIncluded(INCLUDE_SUB_FOLDERS).create();
final ActionImpl expectedAction = new ActionImpl(null, null, ExecuteAllRulesActionExecuter.NAME);
expectedAction.setNodeRef(FOLDER_NODE_REF);
expectedAction.setParameterValues(Map.of(
ExecuteAllRulesActionExecuter.PARAM_RUN_ALL_RULES_ON_CHILDREN, INCLUDE_SUB_FOLDERS,
ExecuteAllRulesActionExecuter.PARAM_EXECUTE_INHERITED_RULES, EXECUTE_INHERITED_RULES,
ActionAccessRestriction.ACTION_CONTEXT_PARAM_NAME, ActionAccessRestriction.V1_ACTION_CONTEXT)
);
final ArgumentCaptor<ActionImpl> actionCaptor = ArgumentCaptor.forClass(ActionImpl.class);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(actionServiceMock).should().executeAction(actionCaptor.capture(), eq(FOLDER_NODE_REF), eq(true), eq(false));
then(actionServiceMock).shouldHaveNoMoreInteractions();
final ActionImpl actualAction = actionCaptor.getValue();
assertThat(actualAction)
.isNotNull()
.usingRecursiveComparison().ignoringFields("id")
.isEqualTo(expectedAction);
assertThat(actualRuleExecution)
.isNotNull()
.usingRecursiveComparison()
.isEqualTo(expectedRuleExecution);
}
private static org.alfresco.service.cmr.rule.Rule createRule(final String id)
{
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);

View File

@@ -0,0 +1,366 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import static org.alfresco.model.ContentModel.TYPE_CATEGORY;
import static org.alfresco.model.ContentModel.TYPE_FOLDER;
import static org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidator.NOT_A_CATEGORY;
import static org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidator.NOT_A_FOLDER;
import static org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidator.NO_PROPER_PERMISSIONS_FOR_NODE;
import static org.alfresco.rest.api.impl.validator.actions.ActionNodeParameterValidator.REQUIRE_READ_PERMISSION_PARAMS;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.CATEGORY;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.NODE_REF;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.TEXT;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.alfresco.service.namespace.NamespaceService.DEFAULT_PREFIX;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter;
import org.alfresco.repo.action.executer.ImageTransformActionExecuter;
import org.alfresco.repo.action.executer.ImporterActionExecuter;
import org.alfresco.repo.action.executer.LinkCategoryActionExecuter;
import org.alfresco.repo.action.executer.MoveActionExecuter;
import org.alfresco.repo.action.executer.SimpleWorkflowActionExecuter;
import org.alfresco.repo.action.executer.TransformActionExecuter;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ActionNodeParameterValidatorTest
{
private static final String READ_RIGHTS_REQUIRED_DEFINITION_ID = LinkCategoryActionExecuter.NAME;
private static final String CATEGORY_NODE_REF_PARAM = REQUIRE_READ_PERMISSION_PARAMS.get(READ_RIGHTS_REQUIRED_DEFINITION_ID).get(0);
private static final String DESTINATION_FOLDER_PARAM = "destination-folder";
private static final String NODE_ID = "node-id";
private static final String COPY_ACTION = CopyActionExecuter.NAME;
@Mock
private Actions actionsMock;
@Mock
private NamespaceService namespaceServiceMock;
@Mock
private Nodes nodesMock;
@Mock
private PermissionService permissionServiceMock;
@InjectMocks
private ActionNodeParameterValidator objectUnderTest;
@Test
public void testProperPermissionsForReadRights()
{
final Action action = new Action();
action.setActionDefinitionId(READ_RIGHTS_REQUIRED_DEFINITION_ID);
action.setParams(Map.of(CATEGORY_NODE_REF_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(CATEGORY_NODE_REF_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(READ_RIGHTS_REQUIRED_DEFINITION_ID)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.ALLOWED);
given(nodesMock.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet())).willReturn(true);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(READ_RIGHTS_REQUIRED_DEFINITION_ID);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).should().nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testNotEnoughPermissionsForReadRights()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
action.setParams(Map.of(DESTINATION_FOLDER_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(DESTINATION_FOLDER_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.DENIED);
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.validate(action));
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidateForNodeNotFound()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
action.setParams(Map.of(DESTINATION_FOLDER_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(DESTINATION_FOLDER_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
given(nodesMock.validateNode(NODE_ID)).willThrow(EntityNotFoundException.class);
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> objectUnderTest.validate(action));
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
}
@Test
public void testProperPermissionsForWriteRights()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
action.setParams(Map.of(DESTINATION_FOLDER_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(DESTINATION_FOLDER_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.ALLOWED);
given(permissionServiceMock.hasPermission(nodeRef, PermissionService.WRITE)).willReturn(AccessStatus.ALLOWED);
given(nodesMock.nodeMatches(nodeRef, Set.of(TYPE_FOLDER), Collections.emptySet())).willReturn(true);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).should().nodeMatches(nodeRef, Set.of(TYPE_FOLDER), Collections.emptySet());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).should().hasPermission(nodeRef, PermissionService.WRITE);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testNotEnoughPermissionsForWriteRights()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
action.setParams(Map.of(DESTINATION_FOLDER_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(DESTINATION_FOLDER_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.ALLOWED);
given(permissionServiceMock.hasPermission(nodeRef, PermissionService.WRITE)).willReturn(AccessStatus.DENIED);
//when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(NO_PROPER_PERMISSIONS_FOR_NODE + NODE_ID);
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).should().hasPermission(nodeRef, PermissionService.WRITE);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testNoValidationExecutedForNonNodeRefParam()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
final String dummyParam = "dummyParam";
action.setParams(Map.of(dummyParam, "dummyValue"));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(dummyParam, TEXT.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).shouldHaveNoInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
}
@Test
public void testWrongTypeOfNodeWhenFolderExpected()
{
final Action action = new Action();
action.setActionDefinitionId(COPY_ACTION);
action.setParams(Map.of(DESTINATION_FOLDER_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(DESTINATION_FOLDER_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(COPY_ACTION, COPY_ACTION, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(COPY_ACTION)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.ALLOWED);
given(permissionServiceMock.hasPermission(nodeRef, PermissionService.WRITE)).willReturn(AccessStatus.ALLOWED);
given(nodesMock.nodeMatches(nodeRef, Set.of(TYPE_FOLDER), Collections.emptySet())).willReturn(false);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(NOT_A_FOLDER + NODE_ID);
then(actionsMock).should().getRuleActionDefinitionById(COPY_ACTION);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).should().nodeMatches(nodeRef, Set.of(TYPE_FOLDER), Collections.emptySet());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).should().hasPermission(nodeRef, PermissionService.WRITE);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testWrongTypeOfNodeWhenCategoryExpected()
{
final Action action = new Action();
action.setActionDefinitionId(READ_RIGHTS_REQUIRED_DEFINITION_ID);
action.setParams(Map.of(CATEGORY_NODE_REF_PARAM, NODE_ID));
ActionDefinition.ParameterDefinition parameterDef =
new ActionDefinition.ParameterDefinition(CATEGORY_NODE_REF_PARAM, NODE_REF.toPrefixString(), false, true, null, null);
final ActionDefinition actionDefinition =
new ActionDefinition(READ_RIGHTS_REQUIRED_DEFINITION_ID, READ_RIGHTS_REQUIRED_DEFINITION_ID, null, null, null, false, false,
List.of(parameterDef));
given(actionsMock.getRuleActionDefinitionById(READ_RIGHTS_REQUIRED_DEFINITION_ID)).willReturn(actionDefinition);
given(namespaceServiceMock.getPrefixes(NODE_REF.getNamespaceURI())).willReturn(List.of(DEFAULT_PREFIX));
final NodeRef nodeRef = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
given(nodesMock.validateNode(NODE_ID)).willReturn(nodeRef);
given(permissionServiceMock.hasReadPermission(nodeRef)).willReturn(AccessStatus.ALLOWED);
given(nodesMock.nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet())).willReturn(false);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(NOT_A_CATEGORY + NODE_ID);
then(actionsMock).should().getRuleActionDefinitionById(READ_RIGHTS_REQUIRED_DEFINITION_ID);
then(actionsMock).shouldHaveNoMoreInteractions();
then(namespaceServiceMock).should().getPrefixes(NODE_REF.getNamespaceURI());
then(namespaceServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).should().validateNode(NODE_ID);
then(nodesMock).should().nodeMatches(nodeRef, Set.of(TYPE_CATEGORY), Collections.emptySet());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(nodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testGetDefinitionIds()
{
final List<String> expectedIds =
List.of(CopyActionExecuter.NAME, MoveActionExecuter.NAME, CheckOutActionExecuter.NAME, ImporterActionExecuter.NAME,
LinkCategoryActionExecuter.NAME, SimpleWorkflowActionExecuter.NAME, TransformActionExecuter.NAME,
ImageTransformActionExecuter.NAME);
final List<String> actualIds = objectUnderTest.getActionDefinitionIds();
assertEquals(expectedIds, actualIds);
}
@Test
public void testHasProperPriority()
{
final int expectedPriority = Integer.MIN_VALUE + 1;
final int actualPriority = objectUnderTest.getPriority();
assertEquals(expectedPriority, actualPriority);
}
}

View File

@@ -0,0 +1,279 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl.validator.actions;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.EMPTY_ACTION_DEFINITION;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.INVALID_ACTION_DEFINITION;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MISSING_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.MUST_NOT_CONTAIN_PARAMETER;
import static org.alfresco.rest.api.impl.validator.actions.ActionParameterDefinitionValidator.PARAMS_SHOULD_NOT_BE_EMPTY;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.BOOLEAN;
import static org.alfresco.service.cmr.dictionary.DataTypeDefinition.TEXT;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.api.Actions;
import org.alfresco.rest.api.model.ActionDefinition;
import org.alfresco.rest.api.model.rules.Action;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class ActionParameterDefinitionValidatorTest
{
private static final String MANDATORY_PARAM_KEY = "paramKey";
private static final String NON_MANDATORY_PARAM_KEY = "nonMandatoryParamKey";
@Mock
private Actions actionsMock;
@InjectMocks
private ActionParameterDefinitionValidator objectUnderTest;
@Test
public void testSimpleValidationPasses()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoParametersNeeded()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, null);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenNoMandatoryParametersNeeded()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final ActionDefinition actionDefinition =
createActionDefinition(actionDefinitionId, List.of(createParameterDefinition(NON_MANDATORY_PARAM_KEY, TEXT, false, null)));
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationPassesWhenOptionalParametersNotProvided()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
objectUnderTest.validate(action);
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenTooManyParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue", NON_MANDATORY_PARAM_KEY, false));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MUST_NOT_CONTAIN_PARAMETER, actionDefinitionId, NON_MANDATORY_PARAM_KEY));
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameters()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(PARAMS_SHOULD_NOT_BE_EMPTY, actionDefinitionId));
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMissingParameterValue()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
final Map<String, java.io.Serializable> params = new HashMap<>();
params.put(MANDATORY_PARAM_KEY, null);
action.setParams(params);
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenMandatoryParameterIsMissing()
{
final Action action = new Action();
final String actionDefinitionId = "properActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(NON_MANDATORY_PARAM_KEY, true));
final List<ActionDefinition.ParameterDefinition> parameterDefinitions =
List.of(createParameterDefinition(MANDATORY_PARAM_KEY, TEXT, true, null),
createParameterDefinition(NON_MANDATORY_PARAM_KEY, BOOLEAN, false, null));
final ActionDefinition actionDefinition = createActionDefinition(actionDefinitionId, parameterDefinitions);
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willReturn(actionDefinition);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(MISSING_PARAMETER, MANDATORY_PARAM_KEY));
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testValidationFailsWhenActionWithNullActionDefinition()
{
final Action action = new Action();
action.setActionDefinitionId(null);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(EMPTY_ACTION_DEFINITION);
then(actionsMock).shouldHaveNoInteractions();
}
@Test
public void testValidationFailsWhenNotApplicableActionDefinition()
{
final Action action = new Action();
final String actionDefinitionId = "notApplicableActionDefinition";
action.setActionDefinitionId(actionDefinitionId);
action.setParams(Map.of(MANDATORY_PARAM_KEY, "paramValue"));
given(actionsMock.getRuleActionDefinitionById(actionDefinitionId)).willThrow(NotFoundException.class);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validate(action))
.withMessageContaining(String.format(INVALID_ACTION_DEFINITION, actionDefinitionId));
then(actionsMock).should().getRuleActionDefinitionById(actionDefinitionId);
then(actionsMock).shouldHaveNoMoreInteractions();
}
@Test
public void testHasProperPriority()
{
final int expectedPriority = Integer.MIN_VALUE;
final int actualPriority = objectUnderTest.getPriority();
assertEquals(expectedPriority, actualPriority);
}
private ActionDefinition createActionDefinition(final String actionDefinitionId,
List<ActionDefinition.ParameterDefinition> parameterDefinitions)
{
return new ActionDefinition(actionDefinitionId, actionDefinitionId, "title", "description", Collections.emptyList(), false, false,
parameterDefinitions);
}
private ActionDefinition.ParameterDefinition createParameterDefinition(final String name, final QName qName, final boolean mandatory,
final String constraint)
{
return new ActionDefinition.ParameterDefinition(name, qName.toPrefixString(), false, mandatory, "label", constraint);
}
}

View File

@@ -24,7 +24,7 @@
* #L%
*/
package org.alfresco.rest.api.nodes;
package org.alfresco.rest.api.rules;
import static org.mockito.BDDMockito.then;

View File

@@ -24,7 +24,7 @@
* #L%
*/
package org.alfresco.rest.api.nodes;
package org.alfresco.rest.api.rules;
import static org.mockito.BDDMockito.then;

Some files were not shown because too many files have changed in this diff Show More