Compare commits

...

120 Commits

Author SHA1 Message Date
Damian.Ujma@hyland.com
cd8ef77b3e Increase sleep to 4 minutes 2022-09-06 12:27:56 +02:00
Damian.Ujma@hyland.com
8622e0e102 Init 2022-09-06 11:10:46 +02:00
Travis CI User
69170dde35 [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-04 00:10:18 +00:00
Travis CI User
c848024130 [maven-release-plugin][skip ci] prepare release 17.101 2022-09-04 00:10:15 +00:00
Alfresco CI User
553f78bb1e [force] Force release for 2022-09-04. 2022-09-04 00:03:36 +00:00
Travis CI User
9a3ceb21a8 [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-03 17:43:30 +00:00
Travis CI User
57d0ff62dc [maven-release-plugin][skip ci] prepare release 17.100 2022-09-03 17:43:27 +00:00
mstrankowski
42bd94c1da ACS-3461: Update ATS reference to released 1.5.4-A3 2022-09-03 18:58:02 +02:00
Travis CI User
c5dd6538f8 [maven-release-plugin][skip ci] prepare for next development iteration 2022-09-01 05:40:58 +00:00
Travis CI User
152c036d86 [maven-release-plugin][skip ci] prepare release 17.99 2022-09-01 05:40:55 +00:00
rrajoria
f2055f91dc Reverting googledrive changes 2022-09-01 10:27:18 +05:30
Travis CI User
a1d7f0d479 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-31 14:01:04 +00:00
Travis CI User
8476f01b35 [maven-release-plugin][skip ci] prepare release 17.98 2022-08-31 14:01:01 +00:00
Maciej Pichura
6c4b9e458a ACS-3431 rule set links TAS REST tests (#1342)
* ACS-3431: Initial TAS REST tests for link to rule set.

* ACS-3431: Fixing assertions.

* ACS-3431: Adding rule set assertions, fixing TAS RESTAPI dependency version.

* ACS-3431: Small test refactorings.

* ACS-3431: Small test refactorings.

* ACS-3431: Adding more tests and refactorings.

* ACS-3431: Fixing a TYPO.
2022-08-31 15:25:25 +02:00
Marcin Strankowski
0f99dec012 ACS-3463: Updating AIS and ATC versions (#1348) 2022-08-31 14:45:25 +02:00
Travis CI User
06c7836e70 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-31 09:54:21 +00:00
Travis CI User
2ceb7384bf [maven-release-plugin][skip ci] prepare release 17.97 2022-08-31 09:54:19 +00:00
rrajoria
d848c83a57 Updating google drive version
Updating google drive version (Test only for JDK 17changes)
2022-08-31 14:46:12 +05:30
Kristian Dimitrov
be7572a978 ACS-3352 GET e2es for newly mapped other fields (#1335)
* ACS-3381: GET e2es for newly mapped other fields

* ACS-3381: Fix failing tests after rebase
2022-08-31 09:53:08 +01:00
Jamal Kaabi-Mofrad
ef45aaf9cc Upgraded Keycloak-Client to match the Identity-Service version. (#1344) 2022-08-30 16:47:37 +01:00
Travis CI User
6f834909f6 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-28 00:10:34 +00:00
Travis CI User
b928598bd7 [maven-release-plugin][skip ci] prepare release 17.96 2022-08-28 00:10:32 +00:00
Alfresco CI User
678eeab278 [force] Force release for 2022-08-28. 2022-08-28 00:04:02 +00:00
Travis CI User
45f9bd6569 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-25 15:41:39 +00:00
Travis CI User
23b8c0e7a6 [maven-release-plugin][skip ci] prepare release 17.95 2022-08-25 15:41:37 +00:00
Antonio Felix
9c98f7b0fb Fix/mnt 23087 export of records failing (#1333)
* MNT-23087 - Split the export list into several smaller list for better performance
2022-08-25 15:36:50 +01:00
Travis CI User
6e1d5c81e2 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-25 11:21:43 +00:00
Travis CI User
092d895f6a [maven-release-plugin][skip ci] prepare release 17.94 2022-08-25 11:21:40 +00:00
Maciej Pichura
a568c87571 ACS-3429, ACS-3336: Rule action mappings (create), validations (update) - part 2 (#1332)
* ACS-3429, ACS-3336: Adding initial TAS tests for create rule with multiple actions, adding action parameters mappings and rule/action validations for rule update.

* ACS-3429: Removing duplicated assertion.

* ACS-3429: Changing NodeRef conversions to use only node id.
2022-08-25 12:46:42 +02:00
Kacper Magdziarz
3aac7be11c MNT-23103 - Downloading a document replaces filename having space with + character (#1327)
* MNT-23103 Change encoder for content disposition filename to be consistent with RFC5987.

Add test covering filename encoding.
2022-08-24 15:59:11 +02:00
Travis CI User
700fbce572 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-24 13:43:15 +00:00
Travis CI User
7be96e788b [maven-release-plugin][skip ci] prepare release 17.93 2022-08-24 13:43:12 +00:00
George Evangelopoulos
0af001be2a Support for linking to a single rule set (#1324)
* Support for linking to a single rule set

* ACS-3435: Small fix to get parent  node for rule set.

* ACS-3435: Revert unnecessary change

* ACS-3435: added tests

* ACS-3435: move test assertions

* ACS-3435: adding tests

Co-authored-by: mpichura <maciej.pichura@hyland.com>
2022-08-24 15:58:04 +03:00
Travis CI User
f38a36910f [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-24 11:57:18 +00:00
Travis CI User
972f81ab8b [maven-release-plugin][skip ci] prepare release 17.92 2022-08-24 11:57:16 +00:00
Domenico Sibilio
1bd0dfd114 ACS-3351 Bump Alfresco JLAN to 7.2 (#1334) 2022-08-24 13:14:03 +02:00
Travis CI User
775de0e94c [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-21 00:10:37 +00:00
Travis CI User
78d2ed247a [maven-release-plugin][skip ci] prepare release 17.91 2022-08-21 00:10:35 +00:00
Alfresco CI User
5ca3630398 [force] Force release for 2022-08-21. 2022-08-21 00:03:38 +00:00
Travis CI User
ee7383dcab [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-19 15:10:22 +00:00
Travis CI User
36b3dc25c0 [maven-release-plugin][skip ci] prepare release 17.90 2022-08-19 15:10:18 +00:00
Maciej Pichura
0b94042b6f ACS-3429 post support for actions (#1305)
* ACS-3429: Initial attemp to add action mappings for create rule.

* ACS-3429: Adding rule action validation (TBC).

* ACS-3429: Adding some basic unit tests.

* ACS-3429: Fixing existing unit tests.

* ACS-3429: Adding some unit tests, small fixes.

* ACS-3429: Fixing existing TAS tests.

* ACS-3429: Fixing test after merge from master.

* ACS-3429: Updating TAS REST dependency.

* ACS-3429: Small fixes after review.

* ACS-3429: Refactoring conversion of action parameters + unit tests adjustments.

* ACS-3429: More unit tests for action parameter conversions.

* ACS-3429: More unit tests for action parameter conversions.

* ACS-3429: Removing unused imports.

* ACS-3429: Adding missing bean definition.
2022-08-19 16:29:37 +02:00
Travis CI User
27d3701c8b [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-18 13:53:38 +00:00
Travis CI User
dc0102001f [maven-release-plugin][skip ci] prepare release 17.89 2022-08-18 13:53:36 +00:00
krdabrowski
12bc363bcd ACS-3353: POST support for "other fields" (#1287) 2022-08-18 14:19:39 +01:00
Tom Page
2ab89f0d79 ACS-3280 Is inheritance enabled rule settings. (#1317)
* ACS-3280 REST tests for -isInheritanceEnabled- setting.

* ACS-3280 Allow setting/getting isInheritanceEnabled for folders.

* ACS-3280 E2E tests for negative cases.

* ACS-3280 Unit tests for RuleSettingsImpl. [tas]

* Update to released TAS REST API. [tas]

* ACS-3280 Code review fixes.

* ACS-3280 Use correct version of TAS. [tas]
2022-08-18 10:53:19 +01:00
Travis CI User
807e509859 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-17 08:57:47 +00:00
Travis CI User
403da286e8 [maven-release-plugin][skip ci] prepare release 17.88 2022-08-17 08:57:45 +00:00
mikolajbrzezinski
cc3f8aaff4 ACS-3316 Fix custom models downloading and XSS (#1304)
* Revert "Revert "ACS-3316 Fix HTML sanitisation bypass (#1266)" (#1294)"

This reverts commit 6c407b1ef5.

* ACS-3316 Set node name for download node

* ACS-3316 Update license

Co-authored-by: Damian.Ujma@hyland.com <Damian.Ujma@hyland.com>
2022-08-17 10:14:40 +02:00
George Evangelopoulos
be925ab67d Change exception type (#1316) 2022-08-16 16:44:29 +03:00
Travis CI User
de4ac000dd [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-15 12:59:40 +00:00
Travis CI User
b2b866e0f9 [maven-release-plugin][skip ci] prepare release 17.87 2022-08-15 12:59:38 +00:00
George Evangelopoulos
984bc151af ACS-3290: V1 REST API endpoint for linking to ruleset (#1269)
* ACS-3290: Endpoint for linking to ruleset

* ACS-3290: Small fixes to REST API endpoint definition.

* ACS-3290: Small fixes in bean initialization.

* ACS-3290: Fix changes after rebasing and add exception message

* ACS-3290: Added unit tests

* ACS-3290: Refactoring and moving logic to RulesImpl interface

* ACS-3290: Remove unused imports and refactoring

* ACS-3290: Formatting

Co-authored-by: mpichura <maciej.pichura@hyland.com>
2022-08-15 15:08:40 +03:00
Travis CI User
b057455cde [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-14 00:10:20 +00:00
Travis CI User
40edaccd1a [maven-release-plugin][skip ci] prepare release 17.86 2022-08-14 00:10:18 +00:00
Alfresco CI User
a802a17d92 [force] Force release for 2022-08-14. 2022-08-14 00:03:42 +00:00
Travis CI User
332626421b [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-12 15:16:34 +00:00
Travis CI User
1baf8d6fae [maven-release-plugin][skip ci] prepare release 17.85 2022-08-12 15:16:32 +00:00
Tom Page
4bae0f2060 ACS-3358 Support isShared field. (#1301)
* Use the new include method.

* ACS-3358 Rename the shared field to isShared.

* ACS-3358 Make isShared an optional field.

* ACS-3358 Add TAS tests for the optional isShared field.

* ACS-3358 Upgrade to release version of TAS REST API. [tas]

* ACS-3358 Update test descriptions.

* ACS-3358 Update toString of Rule.
2022-08-12 15:37:57 +01:00
Travis CI User
0c017ac30c [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-11 15:08:22 +00:00
Travis CI User
cc0940e519 [maven-release-plugin][skip ci] prepare release 17.84 2022-08-11 15:08:19 +00:00
dependabot[bot]
0190b9060a Bump email from 1.8 to 1.9 (#1299) 2022-08-11 14:33:55 +00:00
dependabot[bot]
596e964553 Bump cmis from 1.31 to 1.32 (#1300) 2022-08-11 14:01:09 +00:00
dependabot[bot]
5d22e161d7 Bump webdav from 1.6 to 1.7 (#1296) 2022-08-11 13:59:12 +00:00
dependabot[bot]
bb27430f6a Bump dependency.slf4j.version from 1.7.35 to 1.7.36 (#952) 2022-08-11 13:52:38 +00:00
Travis CI User
1af879a7ed [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-11 11:45:25 +00:00
Travis CI User
c029f5afa3 [maven-release-plugin][skip ci] prepare release 17.83 2022-08-11 11:45:22 +00:00
mstrankowski
3b93814d76 Retry tests 2022-08-11 13:07:19 +02:00
mstrankowski
656ecdc41d [skip tests] Retry release 2022-08-11 13:05:41 +02:00
Travis CI User
8150abf8b7 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-11 10:21:56 +00:00
Travis CI User
cab6fd6d2c [maven-release-plugin][skip ci] prepare release 17.82 2022-08-11 10:21:54 +00:00
dependabot[bot]
e45211ad0f Bump ftp from 1.5 to 1.7 (#1297) 2022-08-11 09:48:29 +00:00
Tom Page
414cba0c1a ACS-3361 Upgrade TAS REST API and check nothing is broken. [tas] (#1295) 2022-08-10 16:42:53 +01:00
Travis CI User
75b74a5d77 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-10 13:25:09 +00:00
Travis CI User
d3efea8873 [maven-release-plugin][skip ci] prepare release 17.81 2022-08-10 13:25:05 +00:00
mikolajbrzezinski
6c407b1ef5 Revert "ACS-3316 Fix HTML sanitisation bypass (#1266)" (#1294)
This reverts commit 885f21ff86.
2022-08-10 14:36:25 +02:00
Travis CI User
f7dcbc6551 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-10 10:31:48 +00:00
Travis CI User
ed1ee00cee [maven-release-plugin][skip ci] prepare release 17.80 2022-08-10 10:31:46 +00:00
Tom Page
bba1664fef ACS-3361 Support for inclusionType. (#1286)
* ACS-3361 Support for inclusionType.

* ACS-3361 Update to released version of TAS Rest API. [tas]

* ACS-3361 Better coverage of different inclusion types. [tas]
2022-08-10 10:58:15 +01:00
Travis CI User
d675d58929 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-09 12:38:17 +00:00
Travis CI User
4f37b984be [maven-release-plugin][skip ci] prepare release 17.79 2022-08-09 12:38:14 +00:00
Marcin Strankowski
9d228add35 Update rest-assured version to 5.1.1, link to newer tas-restapi arti… (#1285)
Update rest-assured version to 5.1.1, link to newer  tas-restapi artifact containing changes
2022-08-09 14:01:44 +02:00
Travis CI User
58d9d0b093 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-09 09:59:45 +00:00
Travis CI User
f8d66ec76d [maven-release-plugin][skip ci] prepare release 17.78 2022-08-09 09:59:42 +00:00
mstrankowski
94a47d0368 [skip tests] Trigger version update 2022-08-09 11:52:24 +02:00
Tom Page
8884cc9563 ACS_3362 GET rule set can include optional owningFolder field. (#1280)
* ACS_3362 GET rule set can include optional owningFolder field. [skip ci]

* ACS_3362 Update to use release version of TAS. [tas]

* ACS_3362 Refactor RuleSetLoader into its own class. [tas]
2022-08-09 10:05:14 +01:00
dependabot[bot]
594f02e7cd Bump junrar from 7.5.2 to 7.5.3 (#1281) 2022-08-09 09:04:42 +00:00
kavitshah-gl
cb29f1e9ec Feature/apps 1550 (#1212)
* Adding test for the stage AGS Smoke UI Tests for actions in RM site

* pushed the createCategoriesTest in APPS-1550 brach

* pushed the createCategoriesTest in APPS-1550 branch

* pushed the CreateFoldersTests in APPS-1550 branch

* [ags]

* ~ /\[ags\]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Revert "~ /\[ags\]"

This reverts commit ed9443e5

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Adding FoldersDispositionScheduleTests

* Added foldersDispositionScheduleWithGhosting

* Added foldersDispositionScheduleWithoutGhosting

* Added RecordsDispositionScheduleTests and other fixes

* Added RecordsDispositionScheduleWithGhostingTests

* [ags api]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Revert "[ags api]"

This reverts commit 2153eafc0f.

* Fixed Review Comments [ags]

Co-authored-by: sbisht <shishuraj.bisht@globallogic.com>
2022-08-09 14:31:28 +05:30
Travis CI User
59816bd071 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-09 08:30:29 +00:00
Travis CI User
bb77023e1f [maven-release-plugin][skip ci] prepare release 17.77 2022-08-09 08:30:26 +00:00
mstrankowski
fa7cb58044 Retrigger master build due to nexus failure 2022-08-09 09:54:43 +02:00
Travis CI User
4962ce1111 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-08 15:24:19 +00:00
Travis CI User
20a0bb7194 [maven-release-plugin][skip ci] prepare release 17.76 2022-08-08 15:24:16 +00:00
dependabot[bot]
1e1bebd19c Bump alfresco-messaging-repo from 1.2.19 to 1.2.20 (#1196) 2022-08-08 14:41:57 +00:00
Travis CI User
03dedb4140 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-08 13:02:05 +00:00
Travis CI User
66f6174b87 [maven-release-plugin][skip ci] prepare release 17.75 2022-08-08 13:02:03 +00:00
mikolajbrzezinski
885f21ff86 ACS-3316 Fix HTML sanitisation bypass (#1266)
* ContentGet context file update

* Get mimetype from ContentReader and check if should be forced to downlaod

* Changes according to comments

* Code duplication removal

* Missing spaces, touch-ups to Javadoc and logic

* tests for slingshot

* Tests for contentGet and formatting changes
2022-08-08 14:26:33 +02:00
Tom Page
501d9204a9 ACS-3360 E2E tests for GET rule sets. [tas] (#1264)
* ACS-3360 GET APIs for rule sets.

Move RulesImpl and RuleSetsImpl into their own package.
Split out node validation into a new class.

* ACS-3360 E2E tests for GET rule sets. [tas]

* ACS-3360 GET APIs for rule sets E2E tests.

* ACS-3360 GET APIs for rule sets E2E tests.

* ACS-3360 GET APIs for rule sets E2E tests.

* ACS-3360 Update comment [skip ci][skip tests]

Co-authored-by: Krystian Dabrowski <krystian.dabrowski@hyland.com>
2022-08-08 11:29:03 +01:00
dependabot[bot]
924005e94e Bump jetty-webapp from 8.2.0.v20160908 to 9.4.34.v20201102 in /remote-api (#270)
* Bump jetty-webapp in /remote-api

Upping jetty to 10.0.11 with a few necessary modifications to avoid errors
Swapping charsets to lowercase, adding ignoring of ambiguous link security issues for jetty (since it is only used in 

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mstrankowski <marcin.strankowski@hyland.com>
2022-08-08 11:59:07 +02:00
Alfresco CI User
3a34c42d2f [force] Force release for 2022-08-07. 2022-08-07 00:03:34 +00:00
Travis CI User
332af85227 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-06 13:46:10 +00:00
Travis CI User
556c13eba0 [maven-release-plugin][skip ci] prepare release 17.74 2022-08-06 13:46:08 +00:00
dependabot[bot]
3caf6bf9f3 Bump alfresco-opencmis-extension from 2.0 to 2.1 (#1277) 2022-08-06 13:07:29 +00:00
Travis CI User
b5fcc5370a [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-06 10:13:41 +00:00
Travis CI User
29007871e8 [maven-release-plugin][skip ci] prepare release 17.73 2022-08-06 10:13:39 +00:00
dependabot[bot]
12df503cc2 Bump restapi from 1.100 to 1.101 (#1279) 2022-08-06 09:22:07 +00:00
Travis CI User
e3a9e9c034 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-06 08:34:50 +00:00
Travis CI User
d116cf397b [maven-release-plugin][skip ci] prepare release 17.72 2022-08-06 08:34:48 +00:00
dependabot[bot]
271c123a00 Bump alfresco-greenmail from 6.2 to 6.4 (#1278) 2022-08-06 08:01:11 +00:00
Travis CI User
5bae1ca9b6 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-06 01:35:04 +00:00
Travis CI User
f84c82c6a2 [maven-release-plugin][skip ci] prepare release 17.71 2022-08-06 01:35:02 +00:00
dependabot[bot]
c639eec1df Bump acs-event-model from 0.0.15 to 0.0.16 (#1274) 2022-08-06 01:03:07 +00:00
Travis CI User
d2e561dc95 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-06 00:37:30 +00:00
Travis CI User
54347fbbee [maven-release-plugin][skip ci] prepare release 17.70 2022-08-06 00:37:28 +00:00
dependabot[bot]
ab0d482179 Bump postgresql from 42.4.0 to 42.4.1 (#1271) 2022-08-06 00:01:23 +00:00
Travis CI User
5fed5292d9 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-05 09:38:41 +00:00
Travis CI User
1e8944a310 [maven-release-plugin][skip ci] prepare release 17.69 2022-08-05 09:38:38 +00:00
Kristian Dimitrov
b97b6751cc ACS-3381: Initial commit (#1272) 2022-08-05 10:04:17 +01:00
Tom Page
af97aca661 ACS-3360 GET APIs for rule sets. (#1263)
ACS-3360 GET APIs for rule sets.

Move RulesImpl and RuleSetsImpl into their own package.
Split out node validation into a new class.
2022-08-04 17:27:51 +02:00
Travis CI User
368acf4724 [maven-release-plugin][skip ci] prepare for next development iteration 2022-08-04 05:56:52 +00:00
103 changed files with 7930 additions and 1316 deletions

11
.github/workflows/hackathon.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
name: Hackathon
on:
push:
jobs:
sleep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: sleep 240

View File

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

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.68</version>
<version>17.102-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.68</version>
<version>17.102-SNAPSHOT</version>
</parent>
<build>
@@ -45,7 +45,7 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>1.7.35</version>
<version>${dependency.slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -74,4 +74,27 @@ public class RecordFoldersAPI extends BaseAPI
return null;
}
public HttpResponse postFolderAction(String user, String password, JSONObject requestParams, String recordFolder) {
String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
try {
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
catch (Exception error) {
LOGGER.error("Unable to extract response parameter", error);
}
return null;
}
public HttpResponse postRecordAction(String user, String password, JSONObject requestParams, String recordId) {
try {
requestParams.put("nodeRef", recordId);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
catch (JSONException error) {
LOGGER.error("Unable to extract response parameter", error);
}
return null;
}
}

View File

@@ -53,9 +53,12 @@ import static org.springframework.http.HttpStatus.OK;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Date;
import java.util.TimeZone;
import java.util.stream.Collectors;
import lombok.Getter;
@@ -91,6 +94,7 @@ import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.UserModel;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
@@ -121,6 +125,8 @@ public class BaseRMRestTest extends RestTest
@Getter(value = PROTECTED)
private SearchAPI searchApi;
protected static final String iso8601_DateFormat="yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
/**
* Asserts the given status code
*
@@ -628,8 +634,8 @@ public class BaseRMRestTest extends RestTest
* Returns search results for the given search term
*
* @param user
* @param term
* @param query language
* @param q
* @param queryLanguage language
* @return
* @throws Exception
*/
@@ -956,5 +962,34 @@ public class BaseRMRestTest extends RestTest
return false;
}
}
/**
* Helper method to get the Previous Date in the YYYY-MM-ddTHH:mm:ss.SSSXXX format
* @param previousDays number of previous days while calculating the date as output
* @return previousDate as String in the ISO 8601 Date Format
*/
protected String getIso8601Date(int previousDays) {
Date date = new Date(System.currentTimeMillis());
Date previousDate = new Date(date.getTime() - previousDays);
// Conversion
SimpleDateFormat sdf= new SimpleDateFormat(iso8601_DateFormat);;
sdf.setTimeZone(TimeZone.getDefault());
return sdf.format(previousDate);
}
/**
* Helper method to provide the Edited Disposition Date Json
* The Edited Disposition Date is modified to previous date so that CUTOFF & DESTROY Steps will be enabled
* @return JsonObject with the format {"name":"editDispositionActionAsOfDate","params":{"asOfDate":{"iso8601":"Previous Date"}}}
*/
protected JSONObject editDispositionDateJson() {
JSONObject requestParams = new JSONObject();
requestParams.put("name","editDispositionActionAsOfDate");
JSONObject params = new JSONObject();
requestParams.put("params",params);
JSONObject asOfDate = new JSONObject();
params.put("asOfDate",asOfDate);
asOfDate.put("iso8601",getIso8601Date(1));
return requestParams;
}
}

View File

@@ -0,0 +1,211 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.DELETE_PERSON;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.LOGIN_SUCCESSFUL;
import static org.alfresco.rest.rm.community.records.SearchRecordsTests.*;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.junit.Assert.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
/**
* Audit Access tests
* @author Kavit Shah
*/
public class AuditAccessTests extends BaseRMRestTest {
private Optional<UserModel> deletedUser;
private final String TEST_PREFIX = generateTestPrefix(AuditAccessTests.class);
private static final String DELETE_USER_EVENT = "Delete User";
private final String record1 = TEST_PREFIX + "RM-2967 uploaded record";
private final String classifiedRecord = TEST_PREFIX + "RM-2967 classified record";
private final String folderName = TEST_PREFIX + "RM-2967 folder";
private final String categoryName = TEST_PREFIX + "RM-2967 category";
private final String editedCategoryName = "edited " + categoryName;
private final String editedFolderName = "edited " + folderName;
private final String editedRecordName = "edited " + record1;
private final String login_successfull = "Login Successful";
private RecordCategory categoryAll;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RecordsAPI recordsAPI;
@Autowired
private RMAuditService rmAuditService;
@Test(priority = 1)
@AlfrescoTest(jira = "RM-2967")
public void deleteRMUsersShowFullAuditTest() {
createTestPrecondition();
updateCategoryMetadata();
updateFolderMetadata();
updateRecordMetadata();
// delete record category and folder with rm_admin_deleted
rmRolesAndActionsAPI.deleteAllItemsInContainer(deletedUser.get().getUsername(), deletedUser.get().getPassword(),
RM_SITE_ID, editedFolderName);
rmRolesAndActionsAPI.deleteAllItemsInContainer(deletedUser.get().getUsername(), deletedUser.get().getPassword(),
RM_SITE_ID, editedCategoryName);
// delete the user
Optional.of(deletedUser).ifPresent(x -> getDataUser().deleteUser(x.get()));
//check for RM-5235 fix
List<AuditEntry> auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getDataUser().usingAdmin().getAdminUser(),
DELETE_PERSON);
assertTrue("Delete user event not found in the audit log.", auditEntries.stream().anyMatch(
auditEntry -> auditEntry.getEvent().equals(DELETE_USER_EVENT)));
}
@Test(priority = 2)
public void filterEventsByLoginSuccessful()
{
createRMSiteIfNotExists();
List<AuditEntry> auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getDataUser().usingAdmin().getAdminUser(),
LOGIN_SUCCESSFUL);
assertFalse("Audit results should contain at least one Login Successful event",
auditEntries.isEmpty());
assertTrue("Audit results contain only Login Successful events",
auditEntries.stream()
.allMatch(e -> e.getEvent().startsWith(LOGIN_SUCCESSFUL.toString()) || e.getEvent().startsWith(login_successfull)));
}
/**
* Creates the required precondition for the test
* <p/>
* See Precondition in current class JavaDoc
*/
private void createTestPrecondition() {
createRMSiteIfNotExists();
// create "rm deleted user" user if it does not exist and assign it to RM Administrator role
createDeletedUser();
// create category and folder
categoryAll = createCategoryIfDoesNotExist(categoryName,deletedUser.get());
createRecordFolderInCategory(folderName,categoryAll,deletedUser.get());
// upload an electronic record
recordsAPI.uploadElectronicRecord(deletedUser.get().getUsername(), deletedUser.get().getPassword(), getDefaultElectronicRecordProperties(record1), folderName, CMISUtil.DocumentType.TEXT_PLAIN);
// upload another electronic record and classify it
recordsAPI.uploadElectronicRecord(deletedUser.get().getUsername(), deletedUser.get().getPassword(), getDefaultElectronicRecordProperties(classifiedRecord), folderName, CMISUtil.DocumentType.TEXT_PLAIN);
}
private void createDeletedUser() {
// create Deleted User
deletedUser = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
deletedUser.get().getUsername(),
ADMIN
);
}
private void updateCategoryMetadata() {
HashMap<BaseAPI.RMProperty, String> categoryProperties = new HashMap<>();
categoryProperties.put(BaseAPI.RMProperty.NAME, editedCategoryName);
categoryProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
categoryProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
// edit some category's properties
String categoryNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + categoryName);
rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), categoryNodeRef, categoryProperties);
}
private void updateFolderMetadata() {
HashMap<BaseAPI.RMProperty, String> folderProperties = new HashMap<>();
folderProperties.put(BaseAPI.RMProperty.NAME, editedFolderName);
folderProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
folderProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
// edit some folder's properties
String folderNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + editedCategoryName + "/" + folderName);
rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), folderNodeRef, folderProperties);
}
private void updateRecordMetadata() {
HashMap<BaseAPI.RMProperty, String> recordProperties = new HashMap<>();
recordProperties.put(BaseAPI.RMProperty.NAME, editedRecordName);
recordProperties.put(BaseAPI.RMProperty.TITLE, "edited " + TITLE);
recordProperties.put(BaseAPI.RMProperty.AUTHOR, "edited author");
recordProperties.put(BaseAPI.RMProperty.DESCRIPTION, "edited " + DESCRIPTION);
// edit some record's properties
String recordName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), editedFolderName, record1);
String recordNodeRef = NODE_PREFIX + rmRolesAndActionsAPI.getItemNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), "/" + editedCategoryName + "/" + editedFolderName + "/" + recordName);
rmRolesAndActionsAPI.updateMetadata(deletedUser.get().getUsername(), deletedUser.get().getPassword(), recordNodeRef, recordProperties);
}
private RecordCategory createCategoryIfDoesNotExist(String CATEGORY_ALL, UserModel deletedUser) {
return createRootCategory(deletedUser, CATEGORY_ALL);
}
private RecordCategoryChild createRecordFolderInCategory(String FOLDER_SEARCH, RecordCategory recordCategory, UserModel deletedUser) {
return createFolder(deletedUser, recordCategory.getId(), FOLDER_SEARCH);
}
private Map<BaseAPI.RMProperty, String> getDefaultElectronicRecordProperties(String recordName) {
Map<BaseAPI.RMProperty, String> defaultProperties = new HashMap<>();
defaultProperties.put(BaseAPI.RMProperty.NAME, recordName);
defaultProperties.put(BaseAPI.RMProperty.TITLE, TITLE);
defaultProperties.put(BaseAPI.RMProperty.DESCRIPTION, DESCRIPTION);
defaultProperties.put(BaseAPI.RMProperty.CONTENT, TEST_CONTENT);
return defaultProperties;
}
}

View File

@@ -0,0 +1,104 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.test.AlfrescoTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.util.Collections;
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME;
import static org.alfresco.rest.rm.community.base.TestData.NONELECTRONIC_RECORD_NAME;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.*;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.*;
public class BasicRulesIntegrationTests extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
private final static String title = "Rule to complete";
private final static String description = "Rule to describe";
private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
@Autowired
private RulesAPI rulesAPI;
@Test
@AlfrescoTest(jira = "RM-2794")
public void basicRulesIntegration() {
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
STEP("Create record categories and record folders");
RecordCategory Category = createRootCategory(getRandomName("recordCategory"));
String recordFolder1 = createRecordFolder(Category.getId(), getRandomName("recFolder")).getId();
//create a rule for completing a record
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
.applyToChildren(true).title(title)
.actions(Collections.singletonList(ActionsOnRule.COMPLETE_RECORD.getActionValue()));
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + Category.getId(), ruleDefinition);
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
//create two electronic record in record folder
String electronicRecordId1 = createElectronicRecord(recordFolder1, ELECTRONIC_RECORD_NAME).getId();
String electronicRecordId2 = createElectronicRecord(recordFolder1, ELECTRONIC_RECORD_NAME).getId();
assertStatusCode(CREATED);
// Update the rules for record Category
rulesAPI.updateRule(getAdminUser().getUsername(), getAdminUser().getPassword(),
NODE_PREFIX + Category.getId(), ruleDefinition.description("description").id(description));
//Delete the root category and rules
deleteRecordCategory(Category.getId());
rulesAPI.deleteAllRulesOnContainer(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + Category.getId());
}
}

View File

@@ -0,0 +1,125 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.test.AlfrescoTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertFalse;
import static org.springframework.http.HttpStatus.OK;
import static org.testng.Assert.assertEquals;
public class CreateCategoriesTests extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
private RecordCategory rootCategory;
private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private RecordCategory Category1;
private RecordCategory Category2;
private RecordCategory SubCategory1;
private RecordCategory SubCategory2;
@BeforeClass(alwaysRun = true)
public void preconditionForCreateCategoriesTests()
{
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
STEP("Create two category");
Category1 = createRootCategory(getRandomName("Category1"));
Category2= createRootCategory(getRandomName("Category2"));
STEP("Create Sub category");
RecordCategoryChild subCategory1 = createRecordCategory(Category1.getId(), getRandomName("subCategory1"));
RecordCategoryChild subCategory2 = createRecordCategory(Category2.getId(), getRandomName("subCategory2"));
}
@Test @AlfrescoTest(jira = "RM-2756")
public void createCategories() throws Exception {
FilePlan filePlan = getRestAPIFactory().getFilePlansAPI().getFilePlan(FILE_PLAN_ALIAS);
STEP("copy category 1 to File Plan.");
getRestAPIFactory().getNodeAPI(toContentModel(Category1.getId())).copy(createBodyForMoveCopy(filePlan.getId()));
STEP("copy category 1 to category 2");
getRestAPIFactory().getNodeAPI(toContentModel(Category1.getId())).copy(createBodyForMoveCopy(Category2.getId()));
String categoryName = "Category name " + getRandomAlphanumeric();
String categoryTitle = "Category title " + getRandomAlphanumeric();
// Create the root record category
RecordCategory Category1 = createRootCategory(categoryName, categoryTitle);
String newCategoryName = "Rename " + categoryName;
// Build the properties which will be updated
RecordCategory recordCategoryUpdated = Category1.builder().name(newCategoryName).build();
// Update the record category
RecordCategory renamedRecordCategory = getRestAPIFactory().getRecordCategoryAPI().updateRecordCategory(recordCategoryUpdated,Category1.getId());
// Verify the status code
assertStatusCode(OK);
// verify renamed component and editTitle component still has this parent
assertEquals(renamedRecordCategory.getParentId(), filePlan.getId());
STEP("move category 1 edited copy to File Plan");
getRestAPIFactory().getNodeAPI(toContentModel(renamedRecordCategory.getId())).move(createBodyForMoveCopy(filePlan.getId()));
assertStatusCode(OK);
// delete All the categories
deleteRecordCategory(Category1.getId());
deleteRecordCategory(Category2.getId());
}
}

View File

@@ -0,0 +1,147 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.common.ReviewPeriod;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderProperties;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.test.AlfrescoTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.*;
public class CreateFoldersTests extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private RecordCategory Category1;
private RecordCategory Category2;
private RecordCategoryChild recordCategoryChild;
@BeforeClass(alwaysRun = true)
public void preconditionForCreateFolderTests() {
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
STEP("Create two category");
Category1 = createRootCategory(getRandomName("Category1"));
Category2 = createRootCategory(getRandomName("Category2"));
// Create a record folder inside the category 1
recordCategoryChild = createRecordFolder(Category1.getId(), getRandomName("recFolder"));
}
@Test
@AlfrescoTest(jira = "RM-2757")
public void createFolders() throws Exception {
// Create record category first
String folderDescription = "The folder description is updated" + getRandomAlphanumeric();
String folderName = "The folder name is updated" + getRandomAlphanumeric();
String folderTitle = "Update title " + getRandomAlphanumeric();
String location = "Location "+ getRandomAlphanumeric();
// Create the record folder properties to update
RecordFolder recordFolder = RecordFolder.builder()
.name(folderName)
.properties(RecordFolderProperties.builder()
.title(folderTitle)
.description(folderDescription)
.vitalRecordIndicator(true)
.reviewPeriod(new ReviewPeriod("month","1"))
.location(location)
.build())
.build();
// Update the record folder
RecordFolder updatedRecordFolder = getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(recordFolder, recordCategoryChild.getId());
// Check the Response Status Code
assertStatusCode(OK);
STEP("copy updated Record in category 1 and category 2");
getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).copy(createBodyForMoveCopy(Category1.getId()));
//assertStatusCode(OK);
getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).copy(createBodyForMoveCopy(Category2.getId()));
//assertStatusCode(OK);
// Delete the Updated folder
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
String recordFolderId = updatedRecordFolder.getId();
recordFolderAPI.deleteRecordFolder(recordFolderId);
// Check the response status code
assertStatusCode(NO_CONTENT);
// Check the record folder is not found
recordFolderAPI.getRecordFolder(recordFolderId);
// Check the response status code
assertStatusCode(NOT_FOUND);
STEP("move updated Record from category 1 to category 2");
getRestAPIFactory().getNodeAPI(toContentModel(updatedRecordFolder.getId())).move(createBodyForMoveCopy(Category2.getId()));
// move category 2 to category 1
getRestAPIFactory().getNodeAPI(toContentModel(Category2.getId())).move(createBodyForMoveCopy(Category1.getId()));
// Delete the record category
RecordCategoryAPI recordCategoryAPI = getRestAPIFactory().getRecordCategoryAPI();
String recordCategoryId = Category1.getId();
recordCategoryAPI.deleteRecordCategory(recordCategoryId);
// Verify the status code
assertStatusCode(NO_CONTENT);
}
}

View File

@@ -0,0 +1,122 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import lombok.Getter;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildEntry;
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.data.DataContent;
import org.alfresco.utility.data.DataSite;
import org.alfresco.utility.data.DataUserAIS;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static lombok.AccessLevel.PROTECTED;
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.CREATED;
public class DeclareDocsAsRecordsOnUpdateRuleNewVersionTests extends BaseRMRestTest {
@Autowired
private DataSite dataSite;
private SiteModel publicSite;
private RecordCategory recordCategory;
@Autowired
private RulesAPI rulesAPI;
@Autowired
protected DataContent dataContent;
@Autowired
@Getter(value = PROTECTED)
protected DataUserAIS dataUser;
private final static String title = "Rule to convert document as record";
@BeforeClass (alwaysRun = true)
public void setUp()
{
publicSite = dataSite.usingAdmin().createPublicRandomSite();
recordCategory = createRootCategory(getRandomName("recordCategory"));
}
@Test
@AlfrescoTest(jira = "RM-1521")
public void declareDocsAsRecordsOnUpdateRuleNewVersion() {
FolderModel testFolder;
STEP("Create test collaboration site to store documents in.");
publicSite = dataSite.usingAdmin().createPublicRandomSite();
STEP("Create a record folder with a DECLARE_AS_RECORD");
RecordCategoryChild folderWithRule = createFolder(recordCategory.getId(), getRandomName("recordFolder"));
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
.applyToChildren(true)
.actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folderWithRule.getId(), ruleDefinition);
STEP("Create a document in the collaboration site");
FileModel testFile = dataContent.usingSite(publicSite)
.usingAdmin()
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
assertStatusCode(CREATED);
// verify the declared record is in Unfilled Records folder
UnfiledContainerAPI unfiledContainersAPI = getRestAPIFactory().getUnfiledContainersAPI();
List<UnfiledContainerChildEntry> matchingRecords = unfiledContainersAPI.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
.getEntries()
.stream()
.filter(e -> e.getEntry().getId().equals(testFile.getNodeRefWithoutVersion()))
.collect(Collectors.toList());
//delete rm items
deleteRecordCategory(recordCategory.getId());
STEP("Delete the record.");
//delete created collaboration site
dataSite.deleteSite(publicSite);
}
}

View File

@@ -0,0 +1,238 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderCollection;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.RecordCategoriesAPI;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.data.DataContent;
import org.alfresco.utility.data.DataSite;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FileType;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.UserModel;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.concurrent.atomic.AtomicReference;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.*;
public class FileAsRecordTests extends BaseRMRestTest {
private static final String CATEGORY_MANAGER = "catManager" + generateTestPrefix(FileAsRecordTests.class);
private static final String CATEGORY_ADMIN = "catAdmin" + generateTestPrefix(FileAsRecordTests.class);
private static final String FOLDER_MANAGER = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
private static final String FOLDER_ADMIN = "recordFolder" + generateTestPrefix(FileAsRecordTests.class);
private UserModel nonRMuser,rmManager;
private SiteModel testSite;
private FileModel document, documentDeclared;
private RecordCategory category_manager, category_admin;
private RecordCategoryChild folder_admin, folder_manager ;
@Autowired
private DataSite dataSite;
@Autowired
private DataContent dataContent;
@Autowired
private RoleService roleService;
@Autowired
private RecordCategoriesAPI recordCategoriesAPI;
/**
* Create preconditions:
* <pre>
* 1. RM site is created
* 2. Two users: user without RM role and a user with RM manager role
* 3. Two Record categories with one folder each
* 4. User with RM MANAGER role has Filling permission over one category
* </pre>
*/
@BeforeClass(alwaysRun = true)
public void preconditionForFileAsRecordRecordTests()
{
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create a user");
nonRMuser = dataUser.createRandomTestUser("testUser");
STEP("Create a collaboration site");
testSite = dataSite.usingUser(nonRMuser).createPublicRandomSite();
STEP("Create a document with the user without RM role");
document = dataContent.usingSite(testSite)
.usingUser(nonRMuser)
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Create two categories with two folders");
category_manager = createRootCategory(CATEGORY_MANAGER);
category_admin = createRootCategory(CATEGORY_ADMIN);
folder_admin = createFolder(category_admin.getId(),FOLDER_ADMIN);
folder_manager = createFolder(category_manager.getId(),FOLDER_MANAGER);
STEP("Create an rm user and give filling permission over CATEGORY_MANAGER record category");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId())
.build();
rmManager = roleService.createCollaboratorWithRMRoleAndPermission(testSite, recordCategory,
UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
}
/**
* Given I have selected the record folder I want to file my declared record to
* When I confirm the action
* Then the dialog closes
* And the document is now shown as a record in the collaboration site
* And if I navigated to the record folder, as any user who had the right permissions, then I would see the
* record filed
*/
@Test
@AlfrescoTest(jira = "RM-6780")
public void checkFileAsRecordToRecordFolder() throws Exception {
AtomicReference<RecordFolderCollection> apiChildren = new AtomicReference<>();
STEP("Create a document with the user with RM role");
documentDeclared = dataContent.usingSite(testSite).usingUser(rmManager)
.createContent(new FileModel("checkDeclareAndFileToRecordFolder", FileType.TEXT_PLAIN));
STEP("Declare and file into a record folder the document uploaded");
getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(documentDeclared,
Utility.buildPath(CATEGORY_MANAGER, FOLDER_MANAGER));
STEP("Check the file is a record within the collaboration site");
try
{
Utility.sleep(1000, 40000, () ->
{
JSONObject collaboratorSearchJson = getSearchApi().liveSearchForDocuments(rmManager.getUsername(),
rmManager.getPassword(),
documentDeclared.getName());
assertTrue("Rm Manager not able to find the document.", collaboratorSearchJson.getJSONArray("items").length() != 0);
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
STEP("Check the record is filed into the record folder.");
// Get children from API
// List children from API
try
{
Utility.sleep(1000, 40000, () ->
{
apiChildren.set((RecordFolderCollection) getRestAPIFactory()
.getRecordFolderAPI(rmManager).getRecordFolderChildren(folder_manager.getId(), "include=properties")
.assertThat().entriesListIsNotEmpty().assertThat().entriesListIsNotEmpty());
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
assertEquals(apiChildren.get()
.getEntries()
.get(0)
.getEntry()
.getProperties()
.getOriginalName(),documentDeclared.getName());
}
/**
* Given I have selected the "File As Record" action
* When I confirm the action without selecting a location to file to
* Then the record is declared in the unfiled folder
*/
@Test
@AlfrescoTest (jira = "RM-6780")
public void fileAsRecordToUnfiledRecordFolder() throws Exception {
STEP("Create a document with the user without RM role");
FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(rmManager)
.createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
FileType.TEXT_PLAIN));
STEP("Click on Declare and file without selecting a record folder");
getRestAPIFactory().getActionsAPI(rmManager).declareAndFile(inplaceRecord,"");
STEP("Check the file is declared in unfiled record folder");
Assert.assertTrue(isMatchingRecordInUnfiledRecords(inplaceRecord), "Record should be filed to Unfiled Records folder");
}
@AfterClass(alwaysRun = true)
public void cleanUpForFileAsRecordRecordTests() {
STEP("Delete the collaboration site");
dataSite.usingUser(nonRMuser).deleteSite(testSite);
STEP("Empty the trashcan.");
restClient.authenticateUser(nonRMuser).withCoreAPI().usingTrashcan().deleteNodeFromTrashcan(toContentModel(testSite.getId()));
getRestAPIFactory()
.getUnfiledContainersAPI(rmManager)
.getUnfiledContainerChildren(UNFILED_RECORDS_CONTAINER_ALIAS)
.getEntries()
.stream()
.forEach(x -> getRestAPIFactory()
.getRecordsAPI()
.deleteRecord(x.getEntry().getId()));
STEP("Cleanup Documents inside folders");
STEP("Delete folders");
getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(folder_admin.getId());
getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(folder_manager.getId());
STEP("Delete categories");
recordCategoriesAPI.deleteCategory(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), category_manager.getName());
recordCategoriesAPI.deleteCategory(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), category_admin.getName());
STEP("Delete Users");
dataUser.deleteUser(nonRMuser);
dataUser.deleteUser(rmManager);
}
}

View File

@@ -0,0 +1,108 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.rest.v0.service.DispositionScheduleService;
import org.alfresco.test.AlfrescoTest;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
public class FoldersDispositionScheduleTests extends BaseRMRestTest {
private RecordCategory Category1;
@Autowired
private DispositionScheduleService dispositionScheduleService;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
private final String TEST_PREFIX = generateTestPrefix(FoldersDispositionScheduleTests.class);
private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
private final String electronicRecord = "RM-2937 electronic 2 record";
private final String nonElectronicRecord = "RM-2937 non-electronic record";
@BeforeClass(alwaysRun = true)
private void setUp(){
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create record category");
Category1 = createRootCategory(getRandomName("Title"));
}
@Test
@AlfrescoTest (jira = "RM-2937")
public void foldersDispositionScheduleWithGhosting() {
//create retention schedule
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
// add cut off step
dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
// add destroy step with ghosting
dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
//create folders
RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(),electronicRecord);
Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(),nonElectronicRecord);
// complete records
completeRecord(elRecord.getId());
completeRecord(nonElRecord.getId());
// edit disposition date
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
// cut off the FOLDER_DESTROY
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
// Destroy the FOLDER_DESTROY
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
}
@AfterMethod(alwaysRun = true)
private void deletePreconditions() {
deleteRecordCategory(Category1.getId());
}
}

View File

@@ -0,0 +1,116 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.rest.v0.service.DispositionScheduleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CREATED_DATE;
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
public class FoldersDispositionScheduleWithoutGhostRecordTests extends BaseRMRestTest {
private RecordCategory Category1;
@Autowired
private DispositionScheduleService dispositionScheduleService;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
private final String TEST_PREFIX = generateTestPrefix(FoldersDispositionScheduleWithoutGhostRecordTests.class);
private final String folderDisposition = TEST_PREFIX + "RM-2937 folder ghosting";
private final String electronicRecord = "RM-2937 electronic 2 record";
private final String nonElectronicRecord = "RM-2937 non-electronic record";
@BeforeClass(alwaysRun = true)
private void setUp(){
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create record category");
Category1 = createRootCategory(getRandomName("Title"));
}
@Test
@AlfrescoTest(jira="RM-2937")
public void foldersDispositionScheduleWithoutGhosting() {
//create retention schedule
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
// add cut off step
dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
// add destroy step with ghosting
dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(Category1.getName(), "day|1", CUT_OFF_DATE);
//create folders
RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(),electronicRecord);
Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(),nonElectronicRecord);
// complete records
completeRecord(elRecord.getId());
completeRecord(nonElRecord.getId());
// edit disposition date
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
// cut off the FOLDER_DESTROY
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),FOLDER_DESTROY.getName());
// edit disposition date
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),FOLDER_DESTROY.getName());
Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
// Destroy the FOLDER_DESTROY
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),FOLDER_DESTROY.getName());
}
@AfterMethod(alwaysRun = true)
private void deletePreconditions() {
deleteRecordCategory(Category1.getId());
}
}

View File

@@ -0,0 +1,202 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.core.v0.RMEvents;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.rest.v0.service.DispositionScheduleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.io.IOException;
import java.time.Instant;
import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
import static org.alfresco.rest.rm.community.model.recordcategory.RetentionPeriodProperty.CUT_OFF_DATE;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.report.log.Step.STEP;
/**
* Contains recordsDispositionScheduleWithoutGhosting test which checks disposition schedule cut off, transfer and destroy without maintaining metadata steps applied to records
* <p/>
* Precondition:
* <p/>
* RM site created, contains an empty category "RM-2801 disposition for records". <p/>
* RM user has RM admin role. <p/>
* A transfer location named "transferred files" is created to which RM user has access
* <p/>
* <img src="doc-files/Disposition Schedule without ghosting.png" alt="Records Disposition Schedule without ghosting" />
*
* @author Kavit Shah
*/
public class RecordsDispositionScheduleTests extends BaseRMRestTest {
/** data prep 6services */
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RecordsAPI recordsAPI;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
@Autowired
private DispositionScheduleService dispositionScheduleService;
private RecordCategory Category1;
private final String TEST_PREFIX = generateTestPrefix(RecordsDispositionScheduleTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private final String recordsCategory = TEST_PREFIX + "RM-2801 category";
private final String folderDisposition = TEST_PREFIX + "RM-2801 folder";
@Test
@AlfrescoTest(jira="RM-2801")
public void recordsDispositionScheduleWithoutGhosting() {
// create test precondition
createTestPrecondition(recordsCategory);
// create disposition schedule
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
// add cut off step
dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
// add transfer step
dispositionScheduleService.addTransferAfterEventStep(Category1.getName(),"transferred records","all_allowances_granted_are_terminated");
// add destroy step without retaining metadata
dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(Category1.getName(), "day|1", CUT_OFF_DATE);
// create a folder and an electronic and a non-electronic record in it
RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
String electronicRecord = "RM-2801 electronic record";
Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(), electronicRecord);
String nonElectronicRecord = "RM-2801 non-electronic record";
Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(), nonElectronicRecord);
// complete records and cut them off
String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
String elRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
getAdminUser().getPassword(), folderDisposition, electronicRecord);
// complete records and cut them off
completeRecord(elRecord.getId());
completeRecord(nonElRecord.getId());
String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
// ensure the complete event action is displayed for both events
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
getAdminUser().getPassword(), nonElRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
getAdminUser().getPassword(), elRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
// Create and Complete transfer
HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition));
String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition));
String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
// edit the disposition schedule date to current date
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
// destroy records
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
// delete category
deleteRecordCategory(Category1.getId());
}
private void createTestPrecondition(String categoryName) {
createRMSiteIfNotExists();
// create "rm admin" user if it does not exist and assign it to RM Administrator role
rmRolesAndActionsAPI.createUserAndAssignToRole(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
// create category
STEP("Create two category");
Category1 = createRootCategory(categoryName,"Title");
}
private String getTransferId(HttpResponse httpResponse,String nodeRef) {
HttpEntity entity = httpResponse.getEntity();
String responseString = null;
try {
responseString = EntityUtils.toString(entity, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject result = new JSONObject(responseString);
return result
.getJSONObject("results")
.get(nodeRef)
.toString();
}
}

View File

@@ -0,0 +1,200 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.core.v0.RMEvents;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.Record;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.rest.v0.service.DispositionScheduleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.io.IOException;
import java.time.Instant;
import static org.alfresco.rest.rm.community.base.TestData.DEFAULT_PASSWORD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.report.log.Step.STEP;
/**
* Contains recordsDispositionScheduleWithGhosting test which checks disposition schedule cut off, transfer and destroy with maintaining record metadata steps applied to records
* <p/>
* Precondition:
* <p/>
* RM site created, contains an empty category "RM-2937 disposition for records with ghosting". <p/>
* RM user has RM admin role. <p/>
* A transfer location named "transferred files with ghosting" is created to which RM user has access
* <p/>
* <img src="doc-files/Disposition Schedule with ghosting.png" alt="Records Disposition Schedule with ghosting" />
*
* @author Kavit Shah
*/
public class RecordsDispositionScheduleWithGhostingTests extends BaseRMRestTest {
/** data prep 6services */
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RecordsAPI recordsAPI;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
@Autowired
private DispositionScheduleService dispositionScheduleService;
private RecordCategory Category1;
private final String TEST_PREFIX = generateTestPrefix(RecordsDispositionScheduleTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private final String recordsCategory = TEST_PREFIX + "RM-2801 category";
private final String folderDisposition = TEST_PREFIX + "RM-2801 folder";
@Test
@AlfrescoTest(jira="RM-2801")
public void recordsDispositionScheduleWithGhosting() {
// create test precondition
createTestPrecondition(recordsCategory);
// create disposition schedule
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), true);
// add cut off step
dispositionScheduleService.addCutOffImmediatelyStep(Category1.getName());
// add transfer step
dispositionScheduleService.addTransferAfterEventStep(Category1.getName(),"transferred records","all_allowances_granted_are_terminated");
// add destroy step without retaining metadata
dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(Category1.getName());
// create a folder and an electronic and a non-electronic record in it
RecordCategoryChild FOLDER_DESTROY = createFolder(getAdminUser(),Category1.getId(),folderDisposition);
String electronicRecord = "RM-2801 electronic record";
Record elRecord = createElectronicRecord(FOLDER_DESTROY.getId(), electronicRecord);
String nonElectronicRecord = "RM-2801 non-electronic record";
Record nonElRecord = createNonElectronicRecord(FOLDER_DESTROY.getId(), nonElectronicRecord);
// complete records and cut them off
String nonElRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
getAdminUser().getPassword(), folderDisposition, nonElectronicRecord);
String elRecordName = recordsAPI.getRecordFullName(getAdminUser().getUsername(),
getAdminUser().getPassword(), folderDisposition, electronicRecord);
// complete records and cut them off
completeRecord(elRecord.getId());
completeRecord(nonElRecord.getId());
String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
// ensure the complete event action is displayed for both events
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
getAdminUser().getPassword(), nonElRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
getAdminUser().getPassword(), elRecordName, RMEvents.ALL_ALLOWANCES_GRANTED_ARE_TERMINATED, Instant.now());
// Create and Complete transfer
HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordName, "/" + Category1.getName() + "/" + folderDisposition));
String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordName, "/" + Category1.getName() + "/" + folderDisposition));
String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
// edit the disposition schedule date to current date
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
Utility.waitToLoopTime(5,"Waiting for Edit Disposition to be processed");
// destroy records
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
// delete category
deleteRecordCategory(Category1.getId());
}
private void createTestPrecondition(String categoryName) {
createRMSiteIfNotExists();
// create "rm admin" user if it does not exist and assign it to RM Administrator role
rmRolesAndActionsAPI.createUserAndAssignToRole(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
RM_ADMIN, DEFAULT_PASSWORD, "Administrator");
// create category
STEP("Create two category");
Category1 = createRootCategory(categoryName,"Title");
}
private String getTransferId(HttpResponse httpResponse,String nodeRef) {
HttpEntity entity = httpResponse.getEntity();
String responseString = null;
try {
responseString = EntityUtils.toString(entity, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}
JSONObject result = new JSONObject(responseString);
return result
.getJSONObject("results")
.get(nodeRef)
.toString();
}
}

View File

@@ -0,0 +1,124 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* 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.rm.community.smoke;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.record.RecordContent;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
import org.alfresco.rest.rm.community.model.rules.ActionsOnRule;
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainer;
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChild;
import org.alfresco.rest.rm.community.model.unfiledcontainer.UnfiledContainerChildProperties;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.test.AlfrescoTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.base.TestData.ELECTRONIC_RECORD_NAME;
import static org.alfresco.rest.rm.community.base.TestData.NONELECTRONIC_RECORD_NAME;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.*;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.*;
public class UnfiledRecordsRuleTests extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
private final String TEST_PREFIX = generateTestPrefix(CreateCategoriesTests.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private RecordCategory Category2;
private RecordCategoryChild Folder2;
@Autowired
private RulesAPI rulesAPI;
@Test
@AlfrescoTest(jira = "RM-2794")
public void unfiledRecordsRule() {
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
STEP("Create record categories and record folders");
Category2 = createRootCategory(getRandomName("recordCategory"));
Folder2 = createFolder(Category2.getId(), getRandomName("recordFolder"));
STEP("Get the unfiled records container");
UnfiledContainer container = getRestAPIFactory().getUnfiledContainersAPI().getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS);
// Check the response code
assertStatusCode(OK);
//create a rule
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
.applyToChildren(true)
.actions(Collections.singletonList(ActionsOnRule.FILE_TO.getActionValue()));
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + container.getId(), ruleDefinition);
//upload an electronic record
UnfiledContainerChild electronicRecord = UnfiledContainerChild.builder()
.name(ELECTRONIC_RECORD_NAME)
.nodeType(CONTENT_TYPE)
.content(RecordContent.builder().mimeType("text/plain").build())
.build();
assertStatusCode(OK);
// create a non-electronic record
UnfiledContainerChild nonelectronicRecord = UnfiledContainerChild.builder()
.properties(UnfiledContainerChildProperties.builder()
.description(NONELECTRONIC_RECORD_NAME)
.title("Title")
.build())
.name(NONELECTRONIC_RECORD_NAME)
.nodeType(NON_ELECTRONIC_RECORD_TYPE)
.build();
assertStatusCode(OK);
//delete the record created, delete the rule from UnfilledRecord page, delete the category created
rulesAPI.deleteAllRulesOnContainer(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + container.getId());
deleteRecordCategory(Category2.getId());
assertStatusCode(NO_CONTENT);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005 - 2020 Alfresco Software Limited.
* Copyright 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.
@@ -40,6 +40,7 @@ import org.json.JSONObject;
import org.junit.Assert;
import org.springframework.extensions.webscripts.TestWebScriptServer;
import org.springframework.extensions.webscripts.TestWebScriptServer.GetRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
import java.io.Serializable;
import java.util.ArrayList;
@@ -194,13 +195,13 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
NodeRef rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content");
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef folderX = createNode(rootFolder, "X", ContentModel.TYPE_FOLDER);
NodeRef folderY = createNode(folderX, "Y", ContentModel.TYPE_FOLDER);
NodeRef folderZ = createNode(folderY, "Z", ContentModel.TYPE_FOLDER);
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content");
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
// uri with relative path at the end
String uri = URL_CONTENT_DOWNLOAD + doc1.getId() + "/X/Y/Z/doc2";
@@ -212,7 +213,50 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
nodeService.deleteNode(rootFolder);
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content)
public void testForcedAttachment() throws Exception
{
Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
NodeRef companyHome = repositoryHelper.getCompanyHome();
NodeRef rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
NodeRef testhtml = createNodeWithTextContent(rootFolder, "testhtml", ContentModel.TYPE_CONTENT, "testhtml content", MimetypeMap.MIMETYPE_HTML);
NodeRef testpdf = createNodeWithTextContent(rootFolder, "testpdf", ContentModel.TYPE_CONTENT, "testpdf content", MimetypeMap.MIMETYPE_PDF);
String uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=false";
GetRequest req = new GetRequest(uri);
Response res = sendRequest(req, 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId();
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=false";
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId();
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
nodeService.deleteNode(rootFolder);
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content, String mimetype)
{
NodeRef nodeRef = createNode(parentNode, nodeCmName, nodeType);
@@ -220,7 +264,7 @@ public class SlingshotContentGetTest extends BaseWebScriptTest
if (content != null)
{
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(content);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,9 +27,11 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.rest.rules.RulesTestsUtils.*;
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.report.log.Step.STEP;
@@ -39,12 +41,17 @@ import static org.springframework.http.HttpStatus.CREATED;
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.List;
import java.util.Map;
import java.util.stream.IntStream;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleModelsCollection;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
@@ -59,6 +66,8 @@ import org.testng.annotations.Test;
@Test(groups = {TestGroup.RULES})
public class CreateRulesTests extends RestTest
{
private static final String IGNORE_ID = "id";
private static final String IGNORE_IS_SHARED = "isShared";
private UserModel user;
private SiteModel site;
private FolderModel ruleFolder;
@@ -71,18 +80,26 @@ public class CreateRulesTests extends RestTest
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
}
/** Check we can create a rule. */
/**
* Check we can create a rule.
* <p>
* Also check that the isShared field is not returned when not requested.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRule()
{
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel ruleModel = createRuleModelWithModifiedValues();
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
expectedRuleModel.setConditions(createEmptyConditionModel());
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is("ruleName");
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
.assertThat().field("id").isNotNull()
.assertThat().field("isShared").isNull();
}
/** Check creating a rule in a non-existent folder returns an error. */
@@ -120,8 +137,7 @@ public class CreateRulesTests extends RestTest
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithEmptyName()
{
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("");
RestRuleModel ruleModel = createRuleModel("");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
@@ -162,41 +178,42 @@ public class CreateRulesTests extends RestTest
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a user without write permission for the folder cannot create a rule in it. */
public void requireWritePermissionToCreateRule()
/** Check that a Collaborator cannot create a rule in a private folder. */
public void siteCollaboratorCannotCreateRule()
{
STEP("Create a user and use them to create a private site containing a folder");
UserModel privateUser = dataUser.createRandomTestUser();
SiteModel privateSite = dataSite.usingUser(privateUser).createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingUser(privateUser).usingSite(privateSite).createFolder();
STEP("Create a collaborator and check they cannot create a rule in the private folder");
UserModel collaborator = dataUser.createRandomTestUser();
dataUser.addUserToSite(collaborator, privateSite, SiteCollaborator);
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(collaborator).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
testRolePermissionsWith(SiteCollaborator);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a user consumer permission for the folder cannot create a rule in it. */
public void failToCreateRuleAsSiteConsumer()
/** Check that a Contributor cannot create a rule in a private folder. */
public void siteContributorCannotCreateRule()
{
STEP("Create a consumer and check they cannot create a rule in the public folder");
UserModel consumer = dataUser.createRandomTestUser();
dataUser.addUserToSite(consumer, site, SiteConsumer);
RestRuleModel ruleModel = new RestRuleModel();
ruleModel.setName("ruleName");
restClient.authenticateUser(consumer).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
testRolePermissionsWith(SiteContributor);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a Consumer cannot create a rule in a private folder. */
public void siteConsumerCannotCreateRule()
{
testRolePermissionsWith(SiteConsumer);
restClient.assertStatusCodeIs(FORBIDDEN);
restClient.assertLastError().containsSummary("Insufficient permissions to manage rules");
}
/** Check that a siteManager can create a rule in a private folder. */
public void siteManagerCanCreateRule()
{
testRolePermissionsWith(SiteManager)
.assertThat().field("id").isNotNull()
.assertThat().field("name").is("testRule");
restClient.assertStatusCodeIs(CREATED);
}
/** Check we can't create a rule under a document node. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void tryToCreateRuleUnderDocument()
@@ -239,7 +256,7 @@ public class CreateRulesTests extends RestTest
{
STEP("Try to create a three rules but the middle one has an error.");
RestRuleModel ruleA = createRuleModel("ruleA");
RestRuleModel ruleB = new RestRuleModel();
RestRuleModel ruleB = createRuleModel("");
// Don't set a name for Rule B.
RestRuleModel ruleC = createRuleModel("ruleC");
List<RestRuleModel> ruleModels = List.of(ruleA, ruleB, ruleC);
@@ -249,4 +266,130 @@ public class CreateRulesTests extends RestTest
restClient.assertStatusCodeIs(BAD_REQUEST);
restClient.assertLastError().containsSummary("Rule name is a mandatory parameter");
}
/** Check we can create a rule without description. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutDescription()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("description").isNull();
}
/** Check we can create a rule without specifying triggers but with the default "inbound" value. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutTriggers()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("triggers").is(List.of("inbound"));
}
/** Check we can create a rule without error script. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithoutErrorScript()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("errorScript").isNull();
}
/** Check we can create a rule with irrelevant isShared flag, and it doesn't have impact to the process. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void createRuleWithSharedFlag()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setIsShared(true);
UserModel admin = dataUser.getAdminUser();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("id").isNotNull()
.assertThat().field("name").is(RULE_NAME_DEFAULT)
.assertThat().field("isShared").isNull();
}
/** Check we can create a rule. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void createRuleAndIncludeFieldsInResponse()
{
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.createSingleRule(ruleModel);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().field("isShared").isNotNull();
}
public 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();
FolderModel privateFolder = dataContent.usingUser(user).usingSite(privateSite).createFolder();
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()));
return restClient.authenticateUser(userWithRole).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
}
/**
* Check we can create a rule with several actions.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void createRuleWithActions()
{
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> 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");
final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, scriptAction));
final UserModel admin = dataUser.getAdminUser();
final RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
final RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
expectedRuleModel.setActions(addActionContextParams(Arrays.asList(copyAction, checkOutAction, scriptAction)));
expectedRuleModel.setConditions(createEmptyConditionModel());
expectedRuleModel.setTriggers(List.of("inbound"));
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
.assertThat().field("isShared").isNull();
}
}

View File

@@ -0,0 +1,210 @@
/*
* #%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.createRuleModel;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.junit.Assert.assertTrue;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.rest.model.RestRuleSetModelsCollection;
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;
/**
* Tests for GET /nodes/{nodeId}/rule-sets and /nodes/{nodeId}/rule-sets/{ruleSetId}.
*/
@Test (groups = { TestGroup.RULES })
public class GetRuleSetsTests extends RestTest
{
private UserModel user;
private SiteModel site;
private FolderModel ruleFolder;
private RestRuleModel rule;
private String ruleSetId;
@BeforeClass (alwaysRun = true)
public void dataPreparation()
{
STEP("Create a user, site and folder.");
user = dataUser.createRandomTestUser();
site = dataSite.usingUser(user).createPublicRandomSite();
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
rule = restClient.authenticateUser(user).withCoreAPI().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)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
}
/** Check we can get an empty list of rule sets. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getEmptyRuleSetsList()
{
STEP("Create a folder in existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Get the rule sets for the folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
.usingNode(folder).getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
assertTrue("Expected no rule sets to be present.", ruleSets.isEmpty());
}
/** Check we can get a list of rule sets. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRuleSetsList()
{
STEP("Get the rule sets for the folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
.getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
ruleSets.assertThat().entriesListCountIs(1);
ruleSets.getEntries().get(0).onModel()
.assertThat().field("id").isNotNull();
}
/** Check we get a 404 if trying to load rule sets for a folder that doesn't exist. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetsForNonExistentFolder()
{
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.assertStatusCodeIs(NOT_FOUND);
}
/** 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()
.usingNode(ruleFolder)
.include("owningFolder")
.getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
ruleSets.getEntries().get(0).onModel()
.assertThat().field("owningFolder").is(ruleFolder.getNodeRef())
.assertThat().field("id").is(ruleSetId);
ruleSets.assertThat().entriesListCountIs(1);
}
/** Check we can get the reason that a rule set is included in the list. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetsAndInclusionType()
{
STEP("Get the rule sets and inclusion type");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
.usingNode(ruleFolder)
.include("inclusionType")
.getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
ruleSets.getEntries().get(0).onModel()
.assertThat().field("inclusionType").is("owned")
.assertThat().field("id").is(ruleSetId);
ruleSets.assertThat().entriesListCountIs(1);
}
/** Check we can get a rule set by its id. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRuleSetById()
{
STEP("Get the rule set using its rule set id");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
.getRuleSet(ruleSetId);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("id").is(ruleSetId);
}
/** Check we can get a rule set using the "-default-" synonym. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getDefaultRuleSetById()
{
STEP("Get the default rule set for the folder");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
.getDefaultRuleSet();
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("id").isNotNull();
}
/** Check we get a 404 if trying to load the default rule set for a folder that doesn't exist. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getDefaultRuleSetForNonExistentFolder()
{
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.assertStatusCodeIs(NOT_FOUND);
}
/** Check we get 404 for a non-existing rule set id. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetByNonExistingId()
{
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.assertStatusCodeIs(NOT_FOUND);
}
/** Check we can get the id of the folder that owns a rule set. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getRuleSetAndOwningFolder()
{
STEP("Get the rule set and owning folder");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI()
.usingNode(ruleFolder)
.include("owningFolder")
.getRuleSet(ruleSetId);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("owningFolder").is(ruleFolder.getNodeRef())
.assertThat().field("id").is(ruleSetId);
}
}

View File

@@ -27,13 +27,14 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
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.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;
@@ -60,6 +61,8 @@ public class GetRulesTests extends RestTest
private FolderModel ruleFolder;
private List<RestRuleModel> createdRules;
private RestRuleModel createdRuleA;
private static final String IGNORE_ID = "id";
private static final String IGNORE_IS_SHARED = "isShared";
@BeforeClass(alwaysRun = true)
public void dataPreparation()
@@ -91,7 +94,11 @@ public class GetRulesTests extends RestTest
assertTrue("Expected no rules to be present.", rules.isEmpty());
}
/** Check we can get all the rules for a folder. */
/**
* Check we can get all the rules for a folder.
* <p>
* Also check that the isShared field is not returned when not requested.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRulesList()
{
@@ -102,8 +109,9 @@ public class GetRulesTests extends RestTest
rules.assertThat().entriesListCountIs(createdRules.size());
IntStream.range(0, createdRules.size()).forEach(i ->
rules.getEntries().get(i).onModel()
.assertThat().field("id").is(createdRules.get(i).getId())
.assertThat().field("name").is(createdRules.get(i).getName()));
.assertThat().field("id").is(createdRules.get(i).getId())
.assertThat().field("name").is(createdRules.get(i).getName())
.assertThat().field("isShared").isNull());
}
/** Check we get a 404 if trying to load rules for a folder that doesn't exist. */
@@ -128,7 +136,33 @@ public class GetRulesTests extends RestTest
restClient.assertStatusCodeIs(NOT_FOUND);
}
/** Check we can get a rule by its id. */
/** Check we can get all the rules for a folder along with the extra "include" and "other" fields. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRulesListWithIncludedFields()
{
STEP("Get the rules that apply to the folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.getListOfRules();
rules.assertThat().entriesListCountIs(createdRules.size());
IntStream.range(0, createdRules.size()).forEach(i ->
rules.getEntries().get(i).onModel()
.assertThat().field("isShared").isNotNull()
.assertThat().field("description").isNull()
.assertThat().field("enabled").is(false)
.assertThat().field("cascade").is(false)
.assertThat().field("asynchronous").is(false)
.assertThat().field("errorScript").isNull()
.assertThat().field("shared").isNull()
.assertThat().field("triggers").is("[inbound]"));
}
/**
* Check we can get a rule by its id.
* <p>
* Also check that the isShared field is not returned when not requested.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getSingleRule()
{
@@ -138,7 +172,56 @@ public class GetRulesTests extends RestTest
restClient.assertStatusCodeIs(OK);
rule.assertThat().field("id").is(createdRuleA.getId())
.assertThat().field("name").is(createdRuleA.getName());
.assertThat().field("name").is(createdRuleA.getName())
.assertThat().field("isShared").isNull();
}
/** Check we can get rule's other fields */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRulesOtherFieldsModified()
{
STEP("Create a rule with all other fields default values modified");
RestRuleModel ruleModel = 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()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
expectedRuleModel.setTriggers(List.of("update"));
expectedRuleModel.setConditions(createEmptyConditionModel());
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
.assertThat().field("id").isNotNull()
.assertThat().field("isShared").isNull();
}
/** Check we can get rule's "other" fields */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getRulesDefaultFields()
{
STEP("Create a rule with all other fields default values");
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
UserModel admin = dataUser.getAdminUser();
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
expectedRuleModel.setTriggers(List.of("inbound"));
expectedRuleModel.setConditions(createEmptyConditionModel());
restClient.assertStatusCodeIs(CREATED);
restClient.assertStatusCodeIs(CREATED);
rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
.assertThat().field("id").isNotNull()
.assertThat().field("isShared").isNull();
}
/** Check we get a 404 if trying to load a rule from a folder that doesn't exist. */
@@ -174,6 +257,18 @@ public class GetRulesTests extends RestTest
restClient.assertStatusCodeIs(NOT_FOUND);
}
/** Check we can get a rule by its id along with any included fields. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getSingleRuleWithIncludedFields()
{
STEP("Load a particular rule");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.include("isShared")
.getSingleRule(createdRuleA.getId());
rule.assertThat().field("isShared").isNotNull();
}
/** Check that a user without read permission cannot view the folder rules. */
public void requireReadPermissionToGetRule()
{

View File

@@ -0,0 +1,313 @@
/*
* #%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.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
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.NOT_FOUND;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleModelsCollection;
import org.alfresco.rest.model.RestRuleSetLinkModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.rest.model.RestRuleSetModelsCollection;
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.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Tests for /nodes/{nodeId}/rule-set-links.
*/
@Test(groups = {TestGroup.RULES})
public class RuleSetLinksTests 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 link to folder containing a rule set.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToFolderContainingRules()
{
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 = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().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)
.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).withCoreAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
expectedLink.setId(ruleSetId);
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
linkedRules.assertThat().entriesListCountIs(1);
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()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
linkedRuleSets.assertThat().entriesListCountIs(1);
final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
expectedRuleSet.setId(ruleSetId);
expectedRuleSet.setInclusionType("linked");
linkedRuleSets.getEntries()
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we can link to a rule set.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToRuleSet()
{
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 = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().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)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
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);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
expectedLink.setId(ruleSetId);
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
linkedRules.assertThat().entriesListCountIs(1);
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()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
likedRuleSets.assertThat().entriesListCountIs(1);
final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
expectedRuleSet.setId(ruleSetId);
expectedRuleSet.setInclusionType("linked");
likedRuleSets.getEntries()
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we get 404 when linking to a non-existing rule set/folder.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToNonExistingRuleSet()
{
STEP("Create a folder in existing site");
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
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);
STEP("Assert link result is 404");
restClient.assertStatusCodeIs(NOT_FOUND);
}
/**
* Check we get bad request error when linking to a folder without rules.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToFolderWithoutRules()
{
STEP("Create 2 folders without rules in existing site");
final FolderModel folder1 = dataContent.usingUser(user).usingSite(site).createFolder();
final FolderModel folder2 = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Link to a folder without rules");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(folder2.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
.assertLastError().containsSummary("The target node has no rules to link.");
}
/**
* Check we get bad request error when linking from a folder which already has rules.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkFromFolderWithRules()
{
STEP("Create folders in existing site");
final FolderModel folder1 = dataContent.usingUser(user).usingSite(site).createFolder();
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()
.createSingleRule(ruleModel1);
RestRuleModel ruleModel2 = createRuleModel("ruleName2");
restClient.authenticateUser(user).withCoreAPI().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);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
.assertLastError().containsSummary(
"Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
}
/**
* Check we get bad request error when linking to a file node.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToFileNode()
{
STEP("Create a folder in existing site");
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
final FileModel fileContent = dataContent.usingUser(user).usingSite(site).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Link to a file node");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(fileContent.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
.assertLastError().containsSummary("NodeId of a folder is expected!");
}
/**
* Check we can link to a parent folder with rules.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkToParentNodeWithRules()
{
STEP("Create parent/child folders in existing site");
final FolderModel parentFolder = dataContent.usingUser(user).usingSite(site).createFolder();
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()
.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)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
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);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
expectedLink.setId(ruleSetId);
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if child folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
.usingNode(childFolder)
.usingDefaultRuleSet()
.getListOfRules();
linkedRules.assertThat().entriesListCountIs(1);
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()
.usingNode(childFolder)
.include("inclusionType")
.getListOfRuleSets();
linkedRuleSets.assertThat().entriesListCountIs(1);
final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
expectedRuleSet.setId(ruleSetId);
expectedRuleSet.setInclusionType("linked");
linkedRuleSets.getEntries()
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
}

View File

@@ -25,17 +25,53 @@
*/
package org.alfresco.rest.rules;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
import org.alfresco.rest.model.RestRuleModel;
public class RulesTestsUtils
{
static final String RULE_NAME_DEFAULT = "ruleName";
static final String RULE_DESCRIPTION_DEFAULT = "rule description";
static final boolean RULE_ENABLED_DEFAULT = true;
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 List<String> ruleTriggersDefault = List.of("inbound", "update", "outbound");
public static RestRuleModel createRuleModel(String name) {
return createRuleModel(name, List.of(createActionModel()));
/**
* Create a rule model filled with default values.
*
* @return The created rule model.
*/
public static RestRuleModel createRuleModelWithModifiedValues()
{
RestRuleModel ruleModel = createRuleModelWithDefaultValues();
ruleModel.setDescription(RULE_DESCRIPTION_DEFAULT);
ruleModel.setEnabled(RULE_ENABLED_DEFAULT);
ruleModel.setCascade(RULE_CASCADE_DEFAULT);
ruleModel.setAsynchronous(RULE_ASYNC_DEFAULT);
ruleModel.setIsShared(RULE_SHARED_DEFAULT);
ruleModel.setTriggers(ruleTriggersDefault);
ruleModel.setErrorScript(RULE_ERROR_SCRIPT_DEFAULT);
return ruleModel;
}
public static RestRuleModel createRuleModelWithDefaultValues()
{
return createRuleModel(RULE_NAME_DEFAULT, List.of(createDefaultActionModel()));
}
public static RestRuleModel createRuleModel(String name)
{
return createRuleModel(name, List.of(createDefaultActionModel()));
}
/**
@@ -58,11 +94,37 @@ public class RulesTestsUtils
*
* @return The created action model.
*/
public static RestActionBodyExecTemplateModel createActionModel()
public static RestActionBodyExecTemplateModel createDefaultActionModel()
{
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
restActionModel.setActionDefinitionId("add-features");
restActionModel.setParams(Map.of("aspect-name", "{http://www.alfresco.org/model/audio/1.0}audio", "actionContext", "rule"));
restActionModel.setActionDefinitionId("set-property-value");
restActionModel.setParams(Map.of("aspect-name", "cm:audio"));
return restActionModel;
}
public static List<RestActionBodyExecTemplateModel> addActionContextParams(List<RestActionBodyExecTemplateModel> inputActions)
{
inputActions.forEach(inputAction -> {
final Map<String, Serializable> params = new HashMap<>((Map<String, Serializable>) inputAction.getParams());
params.put("actionContext", "rule");
inputAction.setParams(params);
});
return inputActions;
}
public static RestActionBodyExecTemplateModel createCustomActionModel(String actionDefinitionId, Map<String, Serializable> params)
{
RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
restActionModel.setActionDefinitionId(actionDefinitionId);
restActionModel.setParams(params);
return restActionModel;
}
public static RestCompositeConditionDefinitionModel createEmptyConditionModel()
{
RestCompositeConditionDefinitionModel conditions = new RestCompositeConditionDefinitionModel();
conditions.setInverted(false);
conditions.setBooleanMode("and");
return conditions;
}
}

View File

@@ -0,0 +1,232 @@
/*
* #%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.requests.RuleSettings.IS_INHERITANCE_ENABLED;
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.NOT_FOUND;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleSettingsModel;
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;
/**
* Tests for GET and PUT /nodes/{nodeId}/rule-settings/{ruleSettingKey}.
*/
@Test (groups = { TestGroup.RULES })
public class SetInheritanceTests extends RestTest
{
private UserModel siteOwner;
private SiteModel site;
@BeforeClass (alwaysRun = true)
public void dataPreparation()
{
STEP("Create a user, site and folder.");
siteOwner = dataUser.createRandomTestUser();
site = dataSite.usingUser(siteOwner).createPrivateRandomSite();
}
/** Check we can get the -isInheritanceEnabled- rule setting for the folder. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getIsInherited()
{
STEP("Create a folder for the test.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
STEP("Get the -isInheritanceEnabled- rule settings for the folder.");
RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(folder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
restClient.assertStatusCodeIs(OK);
RestRuleSettingsModel expected = new RestRuleSettingsModel();
expected.setKey(IS_INHERITANCE_ENABLED);
expected.setValue(true);
ruleSettingsModel.assertThat().isEqualTo(expected);
}
/** Check we get an error when trying to get settings from a non-existent folder. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getIsInheritedFromNonExistentFolder()
{
STEP("Try to get the -isInheritanceEnabled- rule settings for a fake folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(nonExistentFolder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
}
/** Check we get an error when trying to retrieve a non-existent setting. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getNonExistentSetting()
{
STEP("Create a folder for the test.");
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-")
.retrieveSetting();
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("Unrecognised rule setting key -fakeRuleSetting-");
}
/** Check a user without permission for the folder cannot get the -isInheritanceEnabled- rule setting. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void getIsInheritedWithoutPermission()
{
STEP("Create a folder and a user without permission to access it.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
UserModel noPermissionUser = dataUser.createRandomTestUser();
STEP("Try to get the -isInheritanceEnabled- setting without permission.");
restClient.authenticateUser(noPermissionUser)
.withCoreAPI()
.usingResource(folder)
.usingIsInheritanceEnabledRuleSetting()
.retrieveSetting();
restClient.assertLastError().statusCodeIs(FORBIDDEN)
.containsSummary("Cannot read from this node");
}
/** Check we can change the -isInheritanceEnabled- rule setting for the folder. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateIsInherited()
{
STEP("Create a folder for the test.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
STEP("Set -isInheritanceEnabled- to false.");
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(false);
RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
.withCoreAPI()
.usingResource(folder)
.usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertStatusCodeIs(OK);
RestRuleSettingsModel expected = new RestRuleSettingsModel();
expected.setKey(IS_INHERITANCE_ENABLED);
expected.setValue(false);
ruleSettingsModel.assertThat().isEqualTo(expected);
}
/** Check we get an error when trying to set -isInheritanceEnabled- to something other than a boolean. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateInheritedWithBadValue()
{
STEP("Create a folder for the test.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
STEP("Try to set -isInheritanceEnabled- to \"banana\".");
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue("banana");
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(BAD_REQUEST)
.containsSummary("Rule setting " + IS_INHERITANCE_ENABLED + " requires a boolean value.");
}
/** Check we get an error when the folder is not found. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateInheritedWithNonExistentFolder()
{
STEP("Try to set -isInheritanceEnabled- against a fake folder.");
FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
nonExistentFolder.setNodeRef("fake-id");
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(nonExistentFolder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("The entity with id: fake-id was not found");
}
/** Check we get an error when trying to set a non-existent setting. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateNonExistentSetting()
{
STEP("Create a folder for the test.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
STEP("Try to set a fake setting on the folder.");
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingRuleSetting("-fakeRuleSetting-")
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(NOT_FOUND)
.containsSummary("Unrecognised rule setting key -fakeRuleSetting-");
}
/** Check a user without manage permission cannot update the -isInheritanceEnabled- rule setting. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void updateIsInheritedWithoutPermission()
{
STEP("Create a folder and a collaborator.");
FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
UserModel collaborator = dataUser.createRandomTestUser();
collaborator.setUserRole(SiteCollaborator);
restClient.authenticateUser(siteOwner).withCoreAPI().usingSite(site).addPerson(collaborator);
STEP("Try to update the -isInheritanceEnabled- setting without permission.");
RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
updateBody.setValue(true);
restClient.authenticateUser(collaborator).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
.updateSetting(updateBody);
restClient.assertLastError().statusCodeIs(FORBIDDEN)
.containsSummary("Insufficient permissions to manage rules");
}
}

View File

@@ -25,7 +25,7 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
import static org.alfresco.utility.report.log.Step.STEP;
@@ -64,7 +64,11 @@ public class UpdateRulesTests extends RestTest
ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
}
/** Check we can update a rule. */
/**
* Check we can update a rule.
* <p>
* Also check that the isShared field is not returned when not requested.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRule()
{
@@ -77,7 +81,8 @@ public class UpdateRulesTests extends RestTest
restClient.assertStatusCodeIs(OK);
updatedRule.assertThat().field("id").is(rule.getId())
.assertThat().field("name").is("Updated rule name");
.assertThat().field("name").is("Updated rule name")
.assertThat().field("isShared").isNull();
}
/** Check we get a 404 if trying to update a rule in a folder that doesn't exist. */
@@ -156,8 +161,7 @@ public class UpdateRulesTests extends RestTest
RestRuleModel rule = createAndSaveRule("Rule name");
STEP("Try to update the rule to have no name.");
RestRuleModel updatedRuleModel = new RestRuleModel();
updatedRuleModel.setName("");
RestRuleModel updatedRuleModel = createRuleModel("");
restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().updateRule(rule.getId(), updatedRuleModel);
restClient.assertLastError().statusCodeIs(BAD_REQUEST)
@@ -179,9 +183,24 @@ public class UpdateRulesTests extends RestTest
updatedRule.assertThat().field("id").is(rule.getId());
}
/** Check we can update a rule and get the included fields. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void updateRuleWithIncludedFields()
{
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()
.include("isShared")
.updateRule(rule.getId(), updatedRuleModel);
updatedRule.assertThat().field("isShared").isNotNull();
}
private RestRuleModel createAndSaveRule(String name)
{
return createAndSaveRule(name, List.of(createActionModel()));
return createAndSaveRule(name, List.of(createDefaultActionModel()));
}
/**

View File

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

View File

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

42
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.68</version>
<version>17.102-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -45,16 +45,16 @@
<dependency.alfresco-hb-data-sender.version>1.0.12</dependency.alfresco-hb-data-sender.version>
<dependency.alfresco-trashcan-cleaner.version>2.4.1</dependency.alfresco-trashcan-cleaner.version>
<dependency.alfresco-jlan.version>7.1</dependency.alfresco-jlan.version>
<dependency.alfresco-jlan.version>7.2</dependency.alfresco-jlan.version>
<dependency.alfresco-server-root.version>6.0.1</dependency.alfresco-server-root.version>
<dependency.alfresco-messaging-repo.version>1.2.19</dependency.alfresco-messaging-repo.version>
<dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.version>
<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>1.5.3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>2.6.0</dependency.alfresco-transform-core.version>
<dependency.alfresco-greenmail.version>6.2</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.15</dependency.acs-event-model.version>
<dependency.alfresco-transform-service.version>1.5.4-A3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>2.7.0-A1</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.22</dependency.spring.version>
<dependency.antlr.version>3.5.2</dependency.antlr.version>
@@ -74,7 +74,7 @@
<dependency.httpcore.version>4.4.15</dependency.httpcore.version>
<dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version>
<dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version>
<dependency.slf4j.version>1.7.35</dependency.slf4j.version>
<dependency.slf4j.version>1.7.36</dependency.slf4j.version>
<dependency.gytheio.version>0.16</dependency.gytheio.version>
<dependency.groovy.version>3.0.12</dependency.groovy.version>
<dependency.tika.version>2.4.1</dependency.tika.version>
@@ -82,7 +82,7 @@
<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.keycloak.version>15.0.2</dependency.keycloak.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.15.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies (can cause dependency conflicts)-->
<dependency.activemq.version>5.17.1</dependency.activemq.version>
@@ -114,17 +114,17 @@
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
<dependency.postgresql.version>42.4.0</dependency.postgresql.version>
<dependency.postgresql.version>42.4.1</dependency.postgresql.version>
<dependency.mysql.version>8.0.30</dependency.mysql.version>
<dependency.mysql-image.version>8</dependency.mysql-image.version>
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.49</dependency.tas-utility.version>
<dependency.rest-assured.version>3.3.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.100</dependency.tas-restapi.version>
<dependency.tas-cmis.version>1.31</dependency.tas-cmis.version>
<dependency.tas-email.version>1.8</dependency.tas-email.version>
<dependency.tas-webdav.version>1.6</dependency.tas-webdav.version>
<dependency.tas-ftp.version>1.5</dependency.tas-ftp.version>
<dependency.rest-assured.version>5.1.1</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.115</dependency.tas-restapi.version>
<dependency.tas-cmis.version>1.32</dependency.tas-cmis.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>
<dependency.tas-dataprep.version>2.6</dependency.tas-dataprep.version>
<!-- AGS properties shared between community and enterprise -->
@@ -148,7 +148,7 @@
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
<url>https://github.com/Alfresco/alfresco-community-repo</url>
<tag>17.68</tag>
<tag>HEAD</tag>
</scm>
<distributionManagement>
@@ -616,6 +616,12 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-reload4j</artifactId>
<version>${dependency.slf4j.version}</version>
<exclusions>
<exclusion>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>xerces</groupId>
@@ -639,7 +645,7 @@
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>7.5.2</version>
<version>7.5.3</version>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.68</version>
<version>17.102-SNAPSHOT</version>
</parent>
<dependencies>
@@ -130,7 +130,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>8.2.0.v20160908</version>
<version>10.0.11</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -142,19 +142,19 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>8.2.0.v20160908</version>
<version>10.0.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>8.2.0.v20160908</version>
<version>10.0.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.alfresco.cmis.client</groupId>
<artifactId>alfresco-opencmis-extension</artifactId>
<version>2.0</version>
<version>2.1</version>
<scope>test</scope>
<exclusions>
<!-- Duplicates classes from jakarta.transaction:jakarta.transaction-api -->

View File

@@ -0,0 +1,64 @@
/*
* #%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.web.scripts;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.springframework.extensions.webscripts.WebScriptRequest;
public class MimeTypeUtil
{
/**
* Get the file mimetype from the file ContentReader, and if its null then set the mimetype to binary by default
* and try to get the correct one from file extension
*
*
* @param reader reader of the file in the request
* @param req request relating to the file
* @param mimetypeService MimetypeService
*
* @return mimetype of the file as a string
*/
public static String determineMimetype(ContentReader reader, WebScriptRequest req, MimetypeService mimetypeService)
{
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
String extensionPath = req.getExtensionPath();
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
return mimetype;
}
}

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* 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
@@ -26,14 +26,18 @@
package org.alfresco.repo.web.scripts.content;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespaceService;
@@ -65,6 +69,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
private NamespaceService namespaceService;
private ContentService contentService;
private List<String> nonAttachContentTypes = Collections.emptyList();
/**
* @param nonAttachContentTypes List<String>
*/
public void setNonAttachContentTypes(List<String> nonAttachContentTypes)
{
if (nonAttachContentTypes != null && !nonAttachContentTypes.isEmpty())
{
this.nonAttachContentTypes = nonAttachContentTypes;
}
}
/**
* @param servletContext ServletContext
*/
@@ -121,9 +138,7 @@ public class ContentGet extends StreamContent implements ServletContextAware
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + reference.toString());
}
// determine attachment
boolean attach = Boolean.valueOf(req.getParameter("a"));
// render content
QName propertyQName = ContentModel.PROP_CONTENT;
@@ -140,6 +155,19 @@ public class ContentGet extends StreamContent implements ServletContextAware
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
// determine attachment and force download for specific mimetypes - see PRODSEC-5862
boolean attach = Boolean.valueOf(req.getParameter("a"));
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
if (!attach)
{
if (nonAttachContentTypes == null || !nonAttachContentTypes.contains(mimetype))
{
attach = true;
logger.warn("Ignored a=false for " + nodeRef.getId() + " since " + mimetype + " is not in the whitelist for non-attach content types");
}
}
// Stream the content
streamContentLocal(req, res, nodeRef, attach, propertyQName, null);

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.web.scripts.content;
import java.io.IOException;
@@ -33,7 +33,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -79,18 +79,7 @@ public class ContentInfo extends StreamContent
delegate.setAttachment(req, res, attach, attachFileName);
// establish mimetype
String mimetype = reader.getMimetype();
String extensionPath = req.getExtensionPath();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
// set mimetype for the content and the character encoding + length for the stream
res.setContentType(mimetype);

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* 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
@@ -30,6 +30,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@@ -43,6 +44,7 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.web.scripts.MimeTypeUtil;
import org.alfresco.sync.repo.events.EventPublisher;
import org.alfresco.repo.web.util.HttpRangeProcessor;
import org.alfresco.rest.framework.resource.content.CacheDirective;
@@ -58,6 +60,7 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.attachment.Rfc5987Util;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.extensions.webscripts.Cache;
@@ -361,18 +364,7 @@ public class ContentStreamer implements ResourceLoaderAware
setAttachment(req, res, attach, attachFileName);
// establish mimetype
String mimetype = reader.getMimetype();
String extensionPath = req.getExtensionPath();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
String mimetype = MimeTypeUtil.determineMimetype(reader, req, mimetypeService);
res.setHeader(HEADER_ACCEPT_RANGES, "bytes");
try
@@ -482,7 +474,7 @@ public class ContentStreamer implements ResourceLoaderAware
if (req == null)
{
headerValue += "; filename*=UTF-8''" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8)
headerValue += "; filename*=UTF-8''" + encodeFilename(attachFileName)
+ "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"";
}
else
@@ -491,12 +483,12 @@ public class ContentStreamer implements ResourceLoaderAware
boolean isLegacy = (null != userAgent) && (userAgent.contains("MSIE 8") || userAgent.contains("MSIE 7"));
if (isLegacy)
{
headerValue += "; filename=\"" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
headerValue += "; filename=\"" + encodeFilename(attachFileName);
}
else
{
headerValue += "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"; filename*=UTF-8''"
+ URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
+ encodeFilename(attachFileName);
}
}
}
@@ -506,6 +498,21 @@ public class ContentStreamer implements ResourceLoaderAware
res.setHeader("Content-Disposition", headerValue);
}
}
private String encodeFilename(String attachFileName)
{
try
{
return Rfc5987Util.encode(attachFileName);
}
catch (UnsupportedEncodingException e)
{
if (logger.isInfoEnabled())
logger.info(e.getMessage() + " Changing encoder from Rfc5987Util to java.net.URLEncoder.");
return URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
}
}
protected String filterNameForQuotedString(String s)
{

View File

@@ -78,7 +78,7 @@ public abstract class AbstractRuleWebScript extends DeclarativeWebScript
private static final String RULE_OUTBOUND = "outbound";
private static final String ACTION_CHECK_OUT = "check-out";
private static final String CANNOT_CREATE_RULE = "cannot.create.rule.checkout.outbound";
public static final String CANNOT_CREATE_RULE = "cannot.create.rule.checkout.outbound";
protected NodeService nodeService;
protected RuleService ruleService;

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;
import java.util.List;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.api.model.rules.RuleSetLink;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
/**
* Rule sets API.
*/
@Experimental
public interface RuleSets
{
/**
* Get rule sets for a folder.
*
* @param folderNodeId Folder node ID
* @param paging {@link Paging} information
* @param includes List of fields to include in the rule set
* @return {@link CollectionWithPagingInfo} containing a list page of rule sets
*/
CollectionWithPagingInfo<RuleSet> getRuleSets(String folderNodeId, List<String> includes, Paging paging);
/**
* Get the rule set with the given ID and check associations with the folder node.
*
* @param folderNodeId Folder node ID
* @param ruleSetId Rule set ID
* @param includes List of fields to include in the rule set
* @return {@link RuleSet} definition
*/
RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes);
/**
* Link a rule set to a folder
*/
RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId);
}

View File

@@ -0,0 +1,54 @@
/*
* #%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;
import org.alfresco.rest.api.model.rules.RuleSetting;
import org.alfresco.service.Experimental;
/**
* Rule settings API.
*/
@Experimental
public interface RuleSettings
{
/**
* Get the rule setting with the given key.
*
* @param folderId Folder node ID
* @param ruleSettingKey Rule setting key
* @return {@link RuleSetting} The retrieved rule setting object.
*/
RuleSetting getRuleSetting(String folderId, String ruleSettingKey);
/**
* Set the rule setting against the specified folder.
*
* @param folderId The folder to update.
* @param ruleSetting The new rule setting.
* @return The updated rule setting object.
*/
RuleSetting setRuleSetting(String folderId, RuleSetting ruleSetting);
}

View File

@@ -26,6 +26,8 @@
package org.alfresco.rest.api;
import java.util.List;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
@@ -33,8 +35,6 @@ import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.rule.RuleServiceException;
import java.util.List;
/**
* Folder node rules API.
*
@@ -47,10 +47,11 @@ public interface Rules
*
* @param folderNodeId - folder node ID
* @param ruleSetId - rule set ID
* @param includes - The list of optional fields to include in the response.
* @param paging - {@link Paging} information
* @return {@link CollectionWithPagingInfo} containing a list page of folder rules
*/
CollectionWithPagingInfo<Rule> getRules(String folderNodeId, String ruleSetId, Paging paging);
CollectionWithPagingInfo<Rule> getRules(String folderNodeId, String ruleSetId, List<String> includes, Paging paging);
/**
* Get rule for rule's ID and check associations with folder node and rule set node
@@ -58,9 +59,10 @@ public interface Rules
* @param folderNodeId - folder node ID
* @param ruleSetId - rule set ID
* @param ruleId - rule ID
* @param includes - The list of optional fields to include in the response.
* @return {@link Rule} definition
*/
Rule getRuleById(String folderNodeId, String ruleSetId, String ruleId);
Rule getRuleById(String folderNodeId, String ruleSetId, String ruleId, List<String> includes);
/**
* Create new rules (and potentially a rule set if "_default_" is supplied).
@@ -68,11 +70,12 @@ public interface Rules
* @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 rule The definition of the rule.
* @param includes The list of optional fields to include in the response.
* @return The newly created rules.
* @throws InvalidArgumentException If the nodes are not the expected types, or the rule set does not correspond to the folder.
* @throws RuleServiceException If the folder is already linked to another rule set.
*/
List<Rule> createRules(String folderNodeId, String ruleSetId, List<Rule> rule);
List<Rule> createRules(String folderNodeId, String ruleSetId, List<Rule> rule, List<String> includes);
/**
* Update a rule.
@@ -81,9 +84,10 @@ public interface Rules
* @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.
* @return The newly updated rule.
*/
Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule);
Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule, List<String> includes);
/**
* Delete rule for rule's ID and check associations with folder node and rule set node

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 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
@@ -713,6 +713,7 @@ public class CustomModelsImpl implements CustomModels
try
{
NodeRef nodeRef = customModelService.createDownloadNode(modelName, withForm);
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, modelName + DownloadsImpl.DEFAULT_ARCHIVE_EXTENSION);
return new CustomModelDownload(nodeRef);
}
catch (Exception ex)

View File

@@ -0,0 +1,156 @@
/*
* #%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.rules;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.ActionService;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.action.ParameterizedItemDefinition;
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.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.json.JSONArray;
import org.json.JSONException;
@Experimental
public class ActionParameterConverter
{
private final DictionaryService dictionaryService;
private final ActionService actionService;
private final NamespaceService namespaceService;
public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService,
NamespaceService namespaceService)
{
this.dictionaryService = dictionaryService;
this.actionService = actionService;
this.namespaceService = namespaceService;
}
Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
{
final Map<String, Serializable> parameters = new HashMap<>(params.size());
final ParameterizedItemDefinition definition = actionService.getActionDefinition(name);
if (definition == null)
{
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
}
for (Map.Entry<String, Serializable> param : params.entrySet())
{
final ParameterDefinition paramDef = definition.getParameterDefintion(param.getKey());
if (paramDef == null && !definition.getAdhocPropertiesAllowed())
{
throw new InvalidArgumentException(InvalidArgumentException.DEFAULT_MESSAGE_ID, new String[]{param.getKey(), name});
}
if (paramDef != null)
{
final QName typeQName = paramDef.getType();
parameters.put(param.getKey(), convertValue(typeQName, param.getValue()));
} else
{
parameters.put(param.getKey(), param.getValue().toString());
}
}
return parameters;
}
public Serializable convertParamFromServiceModel(Serializable param)
{
if (param instanceof QName)
{
return ((QName) param).toPrefixString(namespaceService);
}
else if (param instanceof NodeRef) {
return ((NodeRef) param).getId();
}
else
{
return param;
}
}
private Serializable convertValue(QName typeQName, Object propertyValue) throws JSONException
{
Serializable value;
final DataTypeDefinition typeDef = dictionaryService.getDataType(typeQName);
if (typeDef == null)
{
throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
}
if (propertyValue instanceof JSONArray)
{
final String javaClassName = typeDef.getJavaClassName();
try
{
Class.forName(javaClassName);
} catch (ClassNotFoundException e)
{
throw new DictionaryException("Java class " + javaClassName + " of property type " + typeDef.getName() + " is invalid", e);
}
final int length = ((JSONArray) propertyValue).length();
final List<Serializable> list = new ArrayList<>(length);
for (int i = 0; i < length; i++)
{
list.add(convertValue(typeQName, ((JSONArray) propertyValue).get(i)));
}
value = (Serializable) list;
}
else
{
if (typeQName.equals(DataTypeDefinition.QNAME) && typeQName.toString().contains(":"))
{
value = QName.createQName(propertyValue.toString(), namespaceService);
}
else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
{
value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, propertyValue.toString());
}
else
{
value = (Serializable) DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(typeQName), propertyValue);
}
}
return value;
}
}

View File

@@ -0,0 +1,85 @@
/*
* #%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.rules;
import static org.alfresco.repo.web.scripts.rule.AbstractRuleWebScript.CANNOT_CREATE_RULE;
import static org.alfresco.service.cmr.rule.RuleType.OUTBOUND;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.repo.action.RuntimeActionService;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.rule.Rule;
import org.apache.commons.collections.CollectionUtils;
@Experimental
public class ActionPermissionValidator
{
private final RuntimeActionService runtimeActionService;
public ActionPermissionValidator(RuntimeActionService runtimeActionService)
{
this.runtimeActionService = runtimeActionService;
}
Rule validateRulePermissions(Rule rule)
{
final List<Action> actions = ((CompositeActionImpl) rule.getAction()).getActions();
checkRestrictedAccessActions(actions);
checkRuleOutboundHasNoCheckOutAction(rule, actions);
return rule;
}
private void checkRestrictedAccessActions(List<Action> actions) {
actions.forEach(action -> {
ActionAccessRestriction.setActionContext(action, ActionAccessRestriction.RULE_ACTION_CONTEXT);
runtimeActionService.verifyActionAccessRestrictions(action);
});
}
private void checkRuleOutboundHasNoCheckOutAction(Rule rule, List<Action> actions) {
//TODO: rule types should never be empty in final implementation
if (CollectionUtils.isNotEmpty(rule.getRuleTypes()) && rule.getRuleTypes().contains(OUTBOUND))
{
for (Action action : actions)
{
if (action.getActionDefinitionName().equalsIgnoreCase(CheckOutActionExecuter.NAME))
{
throw new InvalidArgumentException(CANNOT_CREATE_RULE);
}
}
}
}
}

View File

@@ -23,123 +23,39 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
package org.alfresco.rest.api.impl.rules;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.PermissionService.CHANGE_PERMISSIONS;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
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.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Responsible for validating nodes when working with rules. */
@Experimental
public class RulesImpl implements Rules
public class NodeValidator
{
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
private static final String RULE_SET_EXPECTED_TYPE_NAME = "rule set";
private Nodes nodes;
private PermissionService permissionService;
private RuleService ruleService;
@Override
public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId, final String ruleSetId, final Paging paging)
{
final NodeRef folderNodeRef = validateFolderNode(folderNodeId, false);
final NodeRef ruleSetNodeRef = validateRuleSetNode(ruleSetId, folderNodeRef);
final boolean isShared = isRuleSetNotNullAndShared(ruleSetNodeRef);
final List<Rule> rules = ruleService.getRules(folderNodeRef).stream()
.map(ruleModel -> Rule.from(ruleModel, isShared))
.collect(Collectors.toList());
return ListPage.of(rules, paging);
}
@Override
public Rule getRuleById(final String folderNodeId, final String ruleSetId, final String ruleId)
{
final NodeRef folderNodeRef = validateFolderNode(folderNodeId, false);
final NodeRef ruleSetNodeRef = validateRuleSetNode(ruleSetId, folderNodeRef);
final NodeRef ruleNodeRef = validateRuleNode(ruleId, ruleSetNodeRef);
return Rule.from(ruleService.getRule(ruleNodeRef), isRuleSetNotNullAndShared(ruleSetNodeRef));
}
@Override
public List<Rule> createRules(final String folderNodeId, final String ruleSetId, final List<Rule> rules)
{
final NodeRef folderNodeRef = validateFolderNode(folderNodeId, true);
// Don't validate the ruleset node if -default- is passed since we may need to create it.
final NodeRef ruleSetNodeRef = (RuleSet.isNotDefaultId(ruleSetId)) ? validateRuleSetNode(ruleSetId, folderNodeRef) : null;
return rules.stream()
.map(rule -> rule.toServiceModel(nodes))
.map(rule -> ruleService.saveRule(folderNodeRef, rule))
.map(rule -> Rule.from(rule, isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef)))
.collect(Collectors.toList());
}
@Override
public Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule)
{
LOGGER.debug("Updating rule in folder {}, rule set {}, rule {} to {}", folderNodeId, ruleSetId, ruleId, rule);
NodeRef folderNodeRef = validateFolderNode(folderNodeId, true);
NodeRef ruleSetNodeRef = validateRuleSetNode(ruleSetId, folderNodeRef);
validateRuleNode(ruleId, ruleSetNodeRef);
boolean shared = isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
return Rule.from(ruleService.saveRule(folderNodeRef, rule.toServiceModel(nodes)), shared);
}
@Override
public void deleteRuleById(String folderNodeId, String ruleSetId, String ruleId)
{
final NodeRef folderNodeRef = validateFolderNode(folderNodeId, true);
final NodeRef ruleSetNodeRef = validateRuleSetNode(ruleSetId, folderNodeRef);
final NodeRef ruleNodeRef = validateRuleNode(ruleId, ruleSetNodeRef);
final org.alfresco.service.cmr.rule.Rule rule = ruleService.getRule(ruleNodeRef);
ruleService.removeRule(folderNodeRef, rule);
}
public void setNodes(Nodes nodes)
{
this.nodes = nodes;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
private PermissionService permissionService;
private NodeService nodeService;
/**
* Validates if folder node exists and the user has permission to use it.
@@ -150,23 +66,10 @@ public class RulesImpl implements Rules
* @throws InvalidArgumentException if node is not of an expected type
* @throws PermissionDeniedException if the user doesn't have the appropriate permission for the folder.
*/
private NodeRef validateFolderNode(final String folderNodeId, boolean requireChangePermission)
public NodeRef validateFolderNode(final String folderNodeId, boolean requireChangePermission)
{
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
if (requireChangePermission)
{
if (permissionService.hasPermission(nodeRef, CHANGE_PERMISSIONS) != ALLOWED)
{
throw new PermissionDeniedException("Insufficient permissions to manage rules.");
}
}
else
{
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
{
throw new PermissionDeniedException("Cannot read from this node!");
}
}
validatePermission(requireChangePermission, nodeRef);
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
return nodeRef;
@@ -180,7 +83,7 @@ public class RulesImpl implements Rules
* @return rule set node reference
* @throws InvalidArgumentException in case of not matching associated folder node
*/
private NodeRef validateRuleSetNode(final String ruleSetId, final NodeRef associatedFolderNodeRef)
public NodeRef validateRuleSetNode(final String ruleSetId, final NodeRef associatedFolderNodeRef)
{
if (RuleSet.isDefaultId(ruleSetId))
{
@@ -194,13 +97,24 @@ public class RulesImpl implements Rules
}
final NodeRef ruleSetNodeRef = validateNode(ruleSetId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef)) {
if (!ruleService.isRuleSetAssociatedWithFolder(ruleSetNodeRef, associatedFolderNodeRef))
{
throw new InvalidArgumentException("Rule set is not associated with folder node!");
}
return ruleSetNodeRef;
}
public NodeRef validateRuleSetNode(String linkToNodeId, boolean requireChangePermission)
{
final Node ruleSetNode = nodes.getNode(linkToNodeId);
final ChildAssociationRef primaryParent = nodeService.getPrimaryParent(ruleSetNode.getNodeRef());
final NodeRef parentNode = primaryParent.getParentRef();
validatePermission(requireChangePermission, parentNode);
return parentNode;
}
/**
* Validates if rule node exists and associated rule set node matches.
*
@@ -209,7 +123,7 @@ public class RulesImpl implements Rules
* @return rule node reference
* @throws InvalidArgumentException in case of not matching associated rule set node
*/
private NodeRef validateRuleNode(final String ruleId, final NodeRef associatedRuleSetNodeRef)
public NodeRef validateRuleNode(final String ruleId, final NodeRef associatedRuleSetNodeRef)
{
final NodeRef ruleNodeRef = validateNode(ruleId, RuleModel.TYPE_RULE, null);
if (associatedRuleSetNodeRef != null && !ruleService.isRuleAssociatedWithRuleSet(ruleNodeRef, associatedRuleSetNodeRef))
@@ -228,16 +142,45 @@ public class RulesImpl implements Rules
return nodeRef;
}
private void validatePermission(boolean requireChangePermission, NodeRef nodeRef)
{
if (requireChangePermission)
{
if (permissionService.hasPermission(nodeRef, CHANGE_PERMISSIONS) != ALLOWED)
{
throw new PermissionDeniedException("Insufficient permissions to manage rules.");
}
}
else
{
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
{
throw new PermissionDeniedException("Cannot read from this node!");
}
}
}
private void verifyNodeType(final NodeRef nodeRef, final QName expectedType, final String expectedTypeName)
{
final Set<QName> expectedTypes = Set.of(expectedType);
if (!nodes.nodeMatches(nodeRef, expectedTypes, null)) {
final String expectedTypeLocalName = (expectedTypeName != null)? expectedTypeName : expectedType.getLocalName();
if (!nodes.nodeMatches(nodeRef, expectedTypes, null))
{
final String expectedTypeLocalName = (expectedTypeName != null) ? expectedTypeName : expectedType.getLocalName();
throw new InvalidArgumentException(String.format("NodeId of a %s is expected!", expectedTypeLocalName));
}
}
private boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef, final NodeRef folderNodeRef)
public boolean isRuleSetNode(String nodeId) {
try
{
validateNode(nodeId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
return true;
} catch (InvalidArgumentException e) {
return false;
}
}
public boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef, final NodeRef folderNodeRef)
{
if (ruleSetNodeRef == null && folderNodeRef != null)
{
@@ -250,8 +193,28 @@ public class RulesImpl implements Rules
}
}
private boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef)
public boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef)
{
return ruleSetNodeRef != null && ruleService.isRuleSetShared(ruleSetNodeRef);
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
public void setNodes(Nodes nodes)
{
this.nodes = nodes;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
}

View File

@@ -0,0 +1,64 @@
/*
* #%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.rules;
import java.util.List;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
/** Responsible for creating {@link Rule} objects. */
@Experimental
public class RuleLoader
{
public static final String IS_SHARED = "isShared";
private RuleService ruleService;
private NodeValidator nodeValidator;
public Rule loadRule(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
{
Rule rule = Rule.from(ruleModel);
if (includes != null && includes.contains(IS_SHARED))
{
NodeRef ruleSet = ruleService.getRuleSetNode(ruleModel.getNodeRef());
boolean isShared = nodeValidator.isRuleSetNotNullAndShared(ruleSet);
rule.setIsShared(isShared);
}
return rule;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
public void setNodeValidator(NodeValidator nodeValidator)
{
this.nodeValidator = nodeValidator;
}
}

View File

@@ -0,0 +1,90 @@
/*
* #%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.rules;
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;
import java.util.List;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
/** Responsible for converting a NodeRef into a {@link RuleSet} object. */
@Experimental
public class RuleSetLoader
{
protected static final String OWNING_FOLDER = "owningFolder";
protected static final String INCLUSION_TYPE = "inclusionType";
private NodeService nodeService;
/**
* Load a rule set for the given node ref.
*
* @param ruleSetNodeRef The rule set node.
* @param includes A list of fields to include.
* @return The rule set object.
*/
public RuleSet loadRuleSet(NodeRef ruleSetNodeRef, NodeRef folderNodeRef, List<String> includes)
{
String ruleSetId = ruleSetNodeRef.getId();
RuleSet ruleSet = RuleSet.of(ruleSetId);
if (includes != null)
{
NodeRef parentRef = nodeService.getPrimaryParent(ruleSetNodeRef).getParentRef();
if (includes.contains(OWNING_FOLDER))
{
ruleSet.setOwningFolder(parentRef);
}
if (includes.contains(INCLUSION_TYPE))
{
// In the case that a rule set applies to the given folder for multiple reasons then priority is given to owned, then linked, then inherited.
if (parentRef.equals(folderNodeRef))
{
ruleSet.setInclusionType(OWNED);
}
else
{
boolean linked = nodeService.getParentAssocs(ruleSetNodeRef)
.stream().map(ChildAssociationRef::getParentRef)
.anyMatch(folderNodeRef::equals);
ruleSet.setInclusionType(linked ? LINKED : INHERITED);
}
}
}
return ruleSet;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
}

View File

@@ -0,0 +1,134 @@
/*
* #%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.rules;
import static java.util.stream.Collectors.toList;
import java.util.List;
import java.util.Optional;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.repo.rule.RuntimeRuleService;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.api.model.rules.RuleSetLink;
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.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.rule.RuleService;
@Experimental
public class RuleSetsImpl implements RuleSets
{
private RuleSetLoader ruleSetLoader;
private RuleService ruleService;
private NodeValidator validator;
private NodeService nodeService;
private RuntimeRuleService runtimeRuleService;
@Override
public CollectionWithPagingInfo<RuleSet> getRuleSets(String folderNodeId, List<String> includes, Paging paging)
{
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
NodeRef ruleSetNode = ruleService.getRuleSetNode(folderNode);
List<RuleSet> ruleSets = Optional.ofNullable(ruleSetNode)
.map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
.stream().collect(toList());
return ListPage.of(ruleSets, paging);
}
@Override
public RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes)
{
NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSetId, folderNode);
return ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
}
@Override
public RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId)
{
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);
//The target node should have pre-existing rules to link to
if (!ruleService.hasRules(linkToNodeRef)) {
throw new InvalidArgumentException("The target node has no rules to link.");
}
//The folder shouldn't have any pre-existing rules
if (ruleService.hasRules(folderNodeRef)) {
throw new InvalidArgumentException("Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
}
// Create the destination folder as a secondary child of the first
NodeRef ruleSetNodeRef = runtimeRuleService.getSavedRuleFolderAssoc(linkToNodeRef).getChildRef();
// The required aspect will automatically be added to the node
nodeService.addChild(folderNodeRef, ruleSetNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
RuleSetLink ruleSetLink = new RuleSetLink();
ruleSetLink.setId(ruleSetNodeRef.getId());
return ruleSetLink;
}
public void setRuleSetLoader(RuleSetLoader ruleSetLoader)
{
this.ruleSetLoader = ruleSetLoader;
}
public void setValidator(NodeValidator validator)
{
this.validator = validator;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setRuntimeRuleService(RuntimeRuleService runtimeRuleService)
{
this.runtimeRuleService = runtimeRuleService;
}
}

View File

@@ -0,0 +1,107 @@
/*
* #%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.rules;
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
import static org.alfresco.rest.api.model.rules.RuleSetting.IS_INHERITANCE_ENABLED_KEY;
import java.util.Collections;
import org.alfresco.rest.api.RuleSettings;
import org.alfresco.rest.api.model.rules.RuleSetting;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@Experimental
public class RuleSettingsImpl implements RuleSettings
{
private NodeValidator validator;
private NodeService nodeService;
@Override
public RuleSetting getRuleSetting(String folderId, String ruleSettingKey)
{
NodeRef folderNode = validator.validateFolderNode(folderId, false);
switch (ruleSettingKey)
{
case IS_INHERITANCE_ENABLED_KEY:
return getIsInheritanceEnabled(folderNode);
default:
throw new NotFoundException("Unrecognised rule setting key " + ruleSettingKey);
}
}
private RuleSetting getIsInheritanceEnabled(NodeRef folderNode)
{
boolean inheritanceDisabled = nodeService.hasAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES);
return RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(!inheritanceDisabled).create();
}
@Override
public RuleSetting setRuleSetting(String folderId, RuleSetting ruleSetting)
{
NodeRef folderNode = validator.validateFolderNode(folderId, true);
switch (ruleSetting.getKey())
{
case IS_INHERITANCE_ENABLED_KEY:
return updateIsInheritanceEnabled(folderNode, ruleSetting.getValue());
default:
throw new NotFoundException("Unrecognised rule setting key " + ruleSetting.getKey());
}
}
private RuleSetting updateIsInheritanceEnabled(NodeRef folderNode, Object value)
{
if (!(value instanceof Boolean))
{
throw new IllegalArgumentException("Rule setting " + IS_INHERITANCE_ENABLED_KEY + " requires a boolean value.");
}
if ((boolean) value)
{
nodeService.removeAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES);
}
else
{
nodeService.addAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES, Collections.emptyMap());
}
return RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(value).create();
}
public void setValidator(NodeValidator validator)
{
this.validator = validator;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
}

View File

@@ -0,0 +1,177 @@
/*
* #%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.rules;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleSet;
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.CompositeAction;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Experimental
public class RulesImpl implements Rules
{
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
private Nodes nodes;
private RuleService ruleService;
private NodeValidator validator;
private RuleLoader ruleLoader;
private ActionParameterConverter actionParameterConverter;
private ActionPermissionValidator actionPermissionValidator;
@Override
public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId,
final String ruleSetId,
final List<String> includes,
final Paging paging)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
validator.validateRuleSetNode(ruleSetId, folderNodeRef);
final List<Rule> rules = ruleService.getRules(folderNodeRef).stream()
.map(ruleModel -> loadRuleAndConvertActionParams(ruleModel, includes))
.collect(Collectors.toList());
return ListPage.of(rules, paging);
}
@Override
public Rule getRuleById(final String folderNodeId, final String ruleSetId, final String ruleId, final List<String> includes)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
final NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
final NodeRef ruleNodeRef = validator.validateRuleNode(ruleId, ruleSetNodeRef);
return loadRuleAndConvertActionParams(ruleService.getRule(ruleNodeRef), includes);
}
@Override
public List<Rule> createRules(final String folderNodeId, final String ruleSetId, final List<Rule> rules, final List<String> includes)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, true);
// Don't validate the ruleset node if -default- is passed since we may need to create it.
if (RuleSet.isNotDefaultId(ruleSetId))
{
validator.validateRuleSetNode(ruleSetId, folderNodeRef);
}
return rules.stream()
.map(this::mapToServiceModelAndValidateActions)
.map(rule -> ruleService.saveRule(folderNodeRef, rule))
.map(rule -> loadRuleAndConvertActionParams(rule, includes))
.collect(Collectors.toList());
}
@Override
public Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule, List<String> includes)
{
LOGGER.debug("Updating rule in folder {}, rule set {}, rule {} to {}", folderNodeId, ruleSetId, ruleId, rule);
NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, true);
NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
validator.validateRuleNode(ruleId, ruleSetNodeRef);
return ruleLoader.loadRule(ruleService.saveRule(folderNodeRef, mapToServiceModelAndValidateActions(rule)), includes);
}
@Override
public void deleteRuleById(String folderNodeId, String ruleSetId, String ruleId)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, true);
final NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
final NodeRef ruleNodeRef = validator.validateRuleNode(ruleId, ruleSetNodeRef);
final org.alfresco.service.cmr.rule.Rule rule = ruleService.getRule(ruleNodeRef);
ruleService.removeRule(folderNodeRef, rule);
}
private org.alfresco.service.cmr.rule.Rule mapToServiceModelAndValidateActions(Rule rule)
{
final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes);
final CompositeAction compositeAction = (CompositeAction) serviceModelRule.getAction();
compositeAction.getActions().forEach(action -> action.setParameterValues(
actionParameterConverter.getConvertedParams(action.getParameterValues(), action.getActionDefinitionName())));
return actionPermissionValidator.validateRulePermissions(serviceModelRule);
}
private Rule loadRuleAndConvertActionParams(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
{
final Rule rule = ruleLoader.loadRule(ruleModel, includes);
rule.getActions()
.forEach(a -> a.setParams(a.getParams().entrySet()
.stream()
.collect(Collectors
.toMap(Map.Entry::getKey, e -> actionParameterConverter.convertParamFromServiceModel(e.getValue())))
)
);
return rule;
}
public void setNodes(Nodes nodes)
{
this.nodes = nodes;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
}
public void setValidator(NodeValidator validator)
{
this.validator = validator;
}
public void setRuleLoader(RuleLoader ruleLoader)
{
this.ruleLoader = ruleLoader;
}
public void setActionParameterConverter(ActionParameterConverter actionParameterConverter)
{
this.actionParameterConverter = actionParameterConverter;
}
public void setActionPermissionValidator(ActionPermissionValidator actionPermissionValidator)
{
this.actionPermissionValidator = actionPermissionValidator;
}
}

View File

@@ -34,7 +34,6 @@ import java.util.Objects;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.repo.action.executer.SetPropertyValueActionExecuter;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
@@ -75,7 +74,7 @@ public class Action
*/
public org.alfresco.service.cmr.action.Action toServiceModel(final NodeRef nodeRef)
{
return new ActionImpl(nodeRef, GUID.generate(), SetPropertyValueActionExecuter.NAME, params);
return new ActionImpl(nodeRef, GUID.generate(), this.actionDefinitionId, params);
}
/**

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.model.rules;
import com.fasterxml.jackson.annotation.JsonValue;
import org.alfresco.service.Experimental;
/** The reason why a rule set applies to a folder. */
@Experimental
public enum InclusionType
{
OWNED, INHERITED, LINKED;
/**
* Load an InclusionType from a given string (case insensitively).
*
* @param inclusionType The given string.
* @return The inclusion type.
*/
public static InclusionType from(String inclusionType)
{
return InclusionType.valueOf(inclusionType.toUpperCase());
}
/**
* The lower case version of the inclusion type.
*
* @return A lowercase string.
*/
@JsonValue
public String toString()
{
return super.toString().toLowerCase();
}
}

View File

@@ -30,12 +30,14 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.framework.resource.UniqueId;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.GUID;
@Experimental
public class Rule
@@ -46,9 +48,9 @@ public class Rule
private boolean enabled;
private boolean cascade;
private boolean asynchronous;
private boolean shared;
private Boolean isShared;
private String errorScript;
private List<RuleTrigger> triggers;
private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
private CompositeCondition conditions;
private List<Action> actions;
@@ -58,7 +60,7 @@ public class Rule
* @param ruleModel - {@link org.alfresco.service.cmr.rule.Rule} service POJO
* @return {@link Rule} REST model
*/
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel, final boolean shared)
public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel)
{
if (ruleModel == null)
{
@@ -70,8 +72,7 @@ public class Rule
.description(ruleModel.getDescription())
.enabled(!ruleModel.getRuleDisabled())
.cascade(ruleModel.isAppliedToChildren())
.asynchronous(ruleModel.getExecuteAsynchronously())
.shared(shared);
.asynchronous(ruleModel.getExecuteAsynchronously());
if (ruleModel.getNodeRef() != null) {
builder.id(ruleModel.getNodeRef().getId());
@@ -108,8 +109,21 @@ public class Rule
final NodeRef nodeRef = (id != null) ? nodes.validateOrLookupNode(id, null) : null;
ruleModel.setNodeRef(nodeRef);
ruleModel.setTitle(name);
ruleModel.setDescription(description);
ruleModel.setRuleDisabled(!enabled);
ruleModel.applyToChildren(cascade);
ruleModel.setExecuteAsynchronously(asynchronous);
if (triggers != null)
{
ruleModel.setRuleTypes(triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList()));
}
ruleModel.setAction(Action.toCompositeAction(actions));
if (errorScript != null)
{
final org.alfresco.service.cmr.action.Action compensatingAction = new ActionImpl(null, GUID.generate(), ScriptActionExecuter.NAME);
compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, errorScript);
ruleModel.getAction().setCompensatingAction(compensatingAction);
}
return ruleModel;
}
@@ -185,14 +199,14 @@ public class Rule
this.errorScript = errorScript;
}
public boolean isShared()
public Boolean isIsShared()
{
return shared;
return isShared;
}
public void setShared(boolean shared)
public void setIsShared(Boolean shared)
{
this.shared = shared;
this.isShared = shared;
}
public List<String> getTriggers()
@@ -204,7 +218,15 @@ public class Rule
return triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList());
}
public void setTriggers(List<RuleTrigger> triggers)
public void setTriggers(List<String> triggers)
{
if (triggers != null)
{
this.triggers = triggers.stream().map(RuleTrigger::of).collect(Collectors.toList());
}
}
public void setRuleTriggers(List<RuleTrigger> triggers)
{
this.triggers = triggers;
}
@@ -233,7 +255,7 @@ public class Rule
public String toString()
{
return "Rule{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", description='" + description + '\'' + ", enabled=" + enabled + ", cascade=" + cascade
+ ", asynchronous=" + asynchronous + ", shared=" + shared + ", errorScript='" + errorScript + '\'' + ", triggers=" + triggers + ", conditions=" + conditions
+ ", asynchronous=" + asynchronous + ", isShared=" + isShared + ", errorScript='" + errorScript + '\'' + ", triggers=" + triggers + ", conditions=" + conditions
+ ", actions=" + actions + '}';
}
@@ -245,15 +267,23 @@ public class Rule
if (o == null || getClass() != o.getClass())
return false;
Rule rule = (Rule) o;
return enabled == rule.enabled && cascade == rule.cascade && asynchronous == rule.asynchronous && shared == rule.shared && Objects.equals(id, rule.id) && Objects.equals(
name, rule.name) && Objects.equals(description, rule.description) && Objects.equals(errorScript, rule.errorScript) && Objects.equals(triggers, rule.triggers)
&& Objects.equals(conditions, rule.conditions) && Objects.equals(actions, rule.actions);
return enabled == rule.enabled
&& cascade == rule.cascade
&& asynchronous == rule.asynchronous
&& Objects.equals(isShared, rule.isShared)
&& Objects.equals(id, rule.id)
&& Objects.equals(name, rule.name)
&& Objects.equals(description, rule.description)
&& Objects.equals(errorScript, rule.errorScript)
&& Objects.equals(triggers, rule.triggers)
&& Objects.equals(conditions, rule.conditions)
&& Objects.equals(actions, rule.actions);
}
@Override
public int hashCode()
{
return Objects.hash(id, name, description, enabled, cascade, asynchronous, shared, errorScript, triggers, conditions, actions);
return Objects.hash(id, name, description, enabled, cascade, asynchronous, isShared, errorScript, triggers, conditions, actions);
}
public static Builder builder()
@@ -270,9 +300,9 @@ public class Rule
private boolean enabled;
private boolean cascade;
private boolean asynchronous;
private boolean shared;
private Boolean isShared;
private String errorScript;
private List<RuleTrigger> triggers;
private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
private CompositeCondition conditions;
private List<Action> actions;
@@ -312,9 +342,9 @@ public class Rule
return this;
}
public Builder shared(boolean shared)
public Builder isShared(Boolean isShared)
{
this.shared = shared;
this.isShared = isShared;
return this;
}
@@ -351,9 +381,9 @@ public class Rule
rule.setEnabled(enabled);
rule.setCascade(cascade);
rule.setAsynchronous(asynchronous);
rule.setShared(shared);
rule.setIsShared(isShared);
rule.setErrorScript(errorScript);
rule.setTriggers(triggers);
rule.setRuleTriggers(triggers);
rule.setConditions(conditions);
rule.setActions(actions);
return rule;

View File

@@ -27,8 +27,10 @@
package org.alfresco.rest.api.model.rules;
import java.util.Objects;
import java.util.StringJoiner;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
@Experimental
public class RuleSet
@@ -36,6 +38,8 @@ public class RuleSet
public static final String DEFAULT_ID = "-default-";
private String id;
private NodeRef owningFolder;
private InclusionType inclusionType;
public static RuleSet of(String id)
{
@@ -44,14 +48,6 @@ public class RuleSet
.create();
}
public boolean isNotDefaultId() {
return isNotDefaultId(this.id);
}
public boolean isDefaultId() {
return isDefaultId(this.id);
}
public static boolean isNotDefaultId(final String id) {
return !isDefaultId(id);
}
@@ -70,10 +66,36 @@ public class RuleSet
this.id = id;
}
public NodeRef getOwningFolder()
{
return owningFolder;
}
public void setOwningFolder(NodeRef owningFolder)
{
this.owningFolder = owningFolder;
}
public InclusionType getInclusionType()
{
return inclusionType;
}
public void setInclusionType(InclusionType inclusionType)
{
this.inclusionType = inclusionType;
}
@Override
public String toString()
{
return "RuleSet{" + "id='" + id + '\'' + '}';
return "RuleSet{"
+ new StringJoiner(", ")
.add("id='" + id + "'")
.add("owningFolder='" + owningFolder + "'")
.add("inclusionType='" + inclusionType + "'")
.toString()
+ '}';
}
@Override
@@ -84,13 +106,15 @@ public class RuleSet
if (o == null || getClass() != o.getClass())
return false;
RuleSet ruleSet = (RuleSet) o;
return Objects.equals(id, ruleSet.id);
return Objects.equals(id, ruleSet.id)
&& Objects.equals(owningFolder, ruleSet.owningFolder)
&& inclusionType == ruleSet.inclusionType;
}
@Override
public int hashCode()
{
return Objects.hash(id);
return Objects.hash(id, owningFolder, inclusionType);
}
public static Builder builder()
@@ -101,6 +125,8 @@ public class RuleSet
public static class Builder
{
private String id;
private NodeRef owningFolder;
private InclusionType inclusionType;
public Builder id(String id)
{
@@ -108,10 +134,24 @@ public class RuleSet
return this;
}
public Builder owningFolder(NodeRef owningFolder)
{
this.owningFolder = owningFolder;
return this;
}
public Builder inclusionType(InclusionType inclusionType)
{
this.inclusionType = inclusionType;
return this;
}
public RuleSet create()
{
final RuleSet ruleSet = new RuleSet();
ruleSet.setId(id);
ruleSet.setOwningFolder(owningFolder);
ruleSet.setInclusionType(inclusionType);
return ruleSet;
}
}

View File

@@ -0,0 +1,46 @@
/*
* #%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;
public class RuleSetLink
{
/**
* This id is referring to the node id of the linked-to-folder which contains the ruleset(s)
*/
private String id;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
}

View File

@@ -0,0 +1,126 @@
/*
* #%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 java.util.StringJoiner;
import org.alfresco.rest.framework.resource.UniqueId;
import org.alfresco.service.Experimental;
@Experimental
public class RuleSetting
{
public static final String IS_INHERITANCE_ENABLED_KEY = "-isInheritanceEnabled-";
private String key;
private Object value;
@UniqueId
public String getKey()
{
return key;
}
public void setKey(String key)
{
this.key = key;
}
public Object getValue()
{
return value;
}
public void setValue(Object value)
{
this.value = value;
}
@Override
public String toString()
{
return "RuleSetting{"
+ new StringJoiner(", ")
.add("key=" + key)
.add("value=" + value.toString())
.toString()
+ "}";
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof RuleSetting))
{
return false;
}
RuleSetting that = (RuleSetting) o;
return Objects.equals(key, that.key)
&& Objects.equals(value, that.value);
}
@Override
public int hashCode()
{
return Objects.hash(key, value);
}
public static RuleSetting.Builder builder()
{
return new RuleSetting.Builder();
}
public static class Builder
{
private String key;
private Object value;
public RuleSetting.Builder key(String key)
{
this.key = key;
return this;
}
public RuleSetting.Builder value(Object value)
{
this.value = value;
return this;
}
public RuleSetting create()
{
final RuleSetting ruleSetting = new RuleSetting();
ruleSetting.setKey(key);
ruleSetting.setValue(value);
return ruleSetting;
}
}
}

View File

@@ -31,31 +31,15 @@ import org.alfresco.service.Experimental;
@Experimental
public enum RuleTrigger
{
INBOUND("inbound"),
UPDATE("update"),
OUTBOUND("outbound");
RuleTrigger(String value)
{
this.value = value;
}
private final String value;
INBOUND, UPDATE, OUTBOUND;
public String getValue()
{
return value;
return this.name().toLowerCase();
}
public static RuleTrigger of(final String value)
{
for (RuleTrigger ruleTrigger : values())
{
if (ruleTrigger.value.equals(value)) {
return ruleTrigger;
}
}
return null;
return RuleTrigger.valueOf(value.toUpperCase());
}
}

View File

@@ -0,0 +1,74 @@
/*
* #%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 java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSetLink;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.core.ResourceParameter;
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.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
@RelationshipResource(name = "rule-set-links", entityResource = NodesEntityResource.class, title = "Linking to a rule set")
public class NodeRuleSetLinksRelation implements InitializingBean, RelationshipResourceAction.Create<RuleSetLink>
{
private final RuleSets ruleSets;
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "ruleSets", ruleSets);
}
@WebApiParam(name = "ruleSetLinkRequest", title = "Request body - rule set id",
description = "Request body with rule set id", kind = ResourceParameter.KIND.HTTP_BODY_OBJECT)
@WebApiDescription(title = "Link a rule set to a folder node",
description = "Submits a request to link a rule set to folder",
successStatus = HttpServletResponse.SC_CREATED)
@Override
public List<RuleSetLink> create(String nodeId, List<RuleSetLink> ruleSetLinksBody, Parameters parameters)
{
return ruleSetLinksBody.stream()
.map(r -> ruleSets.linkToRuleSet(nodeId, r.getId()))
.collect(Collectors.toList());
}
public NodeRuleSetLinksRelation(RuleSets ruleSets)
{
this.ruleSets = ruleSets;
}
}

View File

@@ -26,15 +26,84 @@
package org.alfresco.rest.api.nodes;
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.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;
import org.springframework.beans.factory.InitializingBean;
/**
* Folder node rule sets.
*
*/
@Experimental
@RelationshipResource(name = "rule-sets", entityResource = NodesEntityResource.class, title = "Folder node rule sets")
public class NodeRuleSetsRelation
public class NodeRuleSetsRelation implements RelationshipResourceAction.Read<RuleSet>,
RelationshipResourceAction.ReadById<RuleSet>,
InitializingBean
{
private RuleSets ruleSets;
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "ruleSets", ruleSets);
}
/**
* List rule sets for given folder.
* <p>
* - GET /nodes/{folderNodeId}/rule-sets
*
* @param folderNodeId The id of the folder node.
* @param parameters Contains paging information and information about which fields to include
* @return {@link CollectionWithPagingInfo} containing a page of rule sets
*/
@WebApiDescription (
title = "Get rule sets for a folder",
description = "Returns a paged list of rule sets for given node",
successStatus = HttpServletResponse.SC_OK
)
@Override
public CollectionWithPagingInfo<RuleSet> readAll(String folderNodeId, Parameters parameters)
{
return ruleSets.getRuleSets(folderNodeId, parameters.getInclude(), parameters.getPaging());
}
/**
* Get single folder rule for given node's, rule set's and rule's IDs.
* <p>
* - GET /nodes/{folderNodeId}/rule-sets/{ruleSetId}
*
* @param folderNodeId - entity resource context for this relationship
* @param ruleSetId - rule set node ID (associated with folder node)
* @param parameters Contains information about which fields to include
* @return {@link RuleSet} definition
* @throws RelationshipResourceNotFoundException in case resource was not found
*/
@WebApiDescription (
title = "Get rule set",
description = "Returns a single rule set for the given node",
successStatus = HttpServletResponse.SC_OK
)
@Override
public RuleSet readById(String folderNodeId, String ruleSetId, Parameters parameters) throws RelationshipResourceNotFoundException
{
return ruleSets.getRuleSetById(folderNodeId, ruleSetId, parameters.getInclude());
}
public void setRuleSets(RuleSets ruleSets)
{
this.ruleSets = ruleSets;
}
}

View File

@@ -0,0 +1,104 @@
/*
* #%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;
}
}

View File

@@ -26,6 +26,9 @@
package org.alfresco.rest.api.nodes;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.framework.WebApiDescription;
@@ -38,9 +41,6 @@ import org.alfresco.service.Experimental;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* Folder node's rules.
*
@@ -82,7 +82,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
{
final String ruleSetId = parameters.getRelationshipId();
return rules.getRules(folderNodeId, ruleSetId, parameters.getPaging());
return rules.getRules(folderNodeId, ruleSetId, parameters.getInclude(), parameters.getPaging());
}
/**
@@ -106,7 +106,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
{
final String ruleId = parameters.getRelationship2Id();
return rules.getRuleById(folderNodeId, ruleSetId, ruleId);
return rules.getRuleById(folderNodeId, ruleSetId, ruleId, parameters.getInclude());
}
/**
@@ -129,7 +129,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
{
final String ruleSetId = parameters.getRelationshipId();
return rules.createRules(folderNodeId, ruleSetId, ruleList);
return rules.createRules(folderNodeId, ruleSetId, ruleList, parameters.getInclude());
}
/**
@@ -153,7 +153,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
{
String ruleSetId = parameters.getRelationshipId();
String ruleId = parameters.getRelationship2Id();
return rules.updateRuleById(folderNodeId, ruleSetId, ruleId, rule);
return rules.updateRuleById(folderNodeId, ruleSetId, ruleId, rule, parameters.getInclude());
}
/**

View File

@@ -850,10 +850,65 @@
</property>
</bean>
<bean id="rules" class="org.alfresco.rest.api.impl.RulesImpl">
<bean id="nodeValidator" class="org.alfresco.rest.api.impl.rules.NodeValidator">
<property name="nodes" ref="Nodes" />
<property name="permissionService" ref="PermissionService"/>
<property name="permissionService" ref="PermissionService" />
<property name="ruleService" ref="RuleService" />
<property name="nodeService" ref="NodeService"/>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRulesRelation">
<property name="rules" ref="Rules" />
</bean>
<bean id="ruleSetLoader" class="org.alfresco.rest.api.impl.rules.RuleSetLoader">
<property name="nodeService" ref="NodeService" />
</bean>
<bean id="ruleSets" class="org.alfresco.rest.api.impl.rules.RuleSetsImpl">
<property name="ruleSetLoader" ref="ruleSetLoader" />
<property name="validator" ref="nodeValidator" />
<property name="ruleService" ref="RuleService" />
<property name="nodeService" ref="NodeService"/>
<property name="runtimeRuleService" ref="ruleService"/>
</bean>
<bean id="RuleSets" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.alfresco.rest.api.RuleSets" />
<property name="target" ref="ruleSets" />
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean id="ruleLoader" class="org.alfresco.rest.api.impl.rules.RuleLoader">
<property name="ruleService" ref="RuleService" />
<property name="nodeValidator" ref="nodeValidator" />
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetsRelation">
<property name="ruleSets" ref="RuleSets" />
</bean>
<bean id="actionParameterConverter" class="org.alfresco.rest.api.impl.rules.ActionParameterConverter">
<constructor-arg name="actionService" ref="ActionService"/>
<constructor-arg name="dictionaryService" ref="DictionaryService"/>
<constructor-arg name="namespaceService" ref="NamespaceService"/>
</bean>
<bean id="actionPermissionValidator" class="org.alfresco.rest.api.impl.rules.ActionPermissionValidator">
<constructor-arg name="runtimeActionService" ref="actionService"/>
</bean>
<bean id="rules" class="org.alfresco.rest.api.impl.rules.RulesImpl">
<property name="nodes" ref="Nodes" />
<property name="validator" ref="nodeValidator"/>
<property name="ruleService" ref="RuleService" />
<property name="ruleLoader" ref="ruleLoader"/>
<property name="actionParameterConverter" ref="actionParameterConverter"/>
<property name="actionPermissionValidator" ref="actionPermissionValidator"/>
</bean>
<bean id="Rules" class="org.springframework.aop.framework.ProxyFactoryBean">
@@ -866,8 +921,27 @@
</property>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRulesRelation">
<property name="rules" ref="Rules" />
<bean class="org.alfresco.rest.api.nodes.NodeRuleSetLinksRelation">
<constructor-arg name="ruleSets" ref="RuleSets" />
</bean>
<bean id="ruleSettings" class="org.alfresco.rest.api.impl.rules.RuleSettingsImpl">
<property name="validator" ref="nodeValidator" />
<property name="nodeService" ref="NodeService" />
</bean>
<bean id="RuleSettings" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="org.alfresco.rest.api.RuleSettings" />
<property name="target" ref="ruleSettings" />
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean class="org.alfresco.rest.api.nodes.NodeRuleSettingsRelation">
<property name="ruleSettings" ref="RuleSettings" />
</bean>
<bean id="publicapi.mimeTypePropertyLookup" class="org.alfresco.rest.api.lookups.MimeTypePropertyLookup">

View File

@@ -249,6 +249,7 @@
<property name="delegate" ref="webscript.content.streamer" />
<property name="contentService" ref="contentService" />
<property name="repository" ref="repositoryHelper" />
<property name="nonAttachContentTypes" value="#{T(java.util.Arrays).asList('${content.nonAttach.mimetypes}')}" />
</bean>
<!-- Content Info -->

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Share Services AMP
* %%
* 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
@@ -66,13 +66,17 @@ public class ContentGetTest extends BaseWebScriptTest
{
super.setUp();
this.authenticationService = (MutableAuthenticationService) getServer().getApplicationContext()
.getBean("AuthenticationService");
this.authenticationService = (MutableAuthenticationService)getServer().getApplicationContext().getBean("AuthenticationService");
this.personService = (PersonService) getServer().getApplicationContext().getBean("PersonService");
this.nodeService = (NodeService) getServer().getApplicationContext().getBean("NodeService");
this.contentService = (ContentService) getServer().getApplicationContext().getBean("ContentService");
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
createUser(USER_ONE);
Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
NodeRef companyHome = repositoryHelper.getCompanyHome();
rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
}
private void createUser(String userName)
@@ -117,18 +121,13 @@ public class ContentGetTest extends BaseWebScriptTest
*/
public void testRelativePath() throws Exception
{
Repository repositoryHelper = (Repository) getServer().getApplicationContext().getBean("repositoryHelper");
NodeRef companyHome = repositoryHelper.getCompanyHome();
rootFolder = createNode(companyHome, "rootFolder", ContentModel.TYPE_FOLDER);
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content");
NodeRef doc1 = createNodeWithTextContent(rootFolder, "doc1", ContentModel.TYPE_CONTENT, "doc1 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
NodeRef folderX = createNode(rootFolder, "X", ContentModel.TYPE_FOLDER);
NodeRef folderY = createNode(folderX, "Y", ContentModel.TYPE_FOLDER);
NodeRef folderZ = createNode(folderY, "Z", ContentModel.TYPE_FOLDER);
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content");
NodeRef doc2 = createNodeWithTextContent(folderZ, "doc2", ContentModel.TYPE_CONTENT, "doc2 file content", MimetypeMap.MIMETYPE_TEXT_PLAIN);
// uri with relative path at the end
String uri = URL_CONTENT_DOWNLOAD + doc1.getId() + "/X/Y/Z/doc2";
@@ -138,7 +137,46 @@ public class ContentGetTest extends BaseWebScriptTest
Assert.assertEquals("doc2 file content", resp.getContentAsString());
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content)
public void testForcedAttachment() throws Exception
{
NodeRef testhtml = createNodeWithTextContent(rootFolder, "testhtml", ContentModel.TYPE_CONTENT, "testhtml content", MimetypeMap.MIMETYPE_HTML);
NodeRef testpdf = createNodeWithTextContent(rootFolder, "testpdf", ContentModel.TYPE_CONTENT, "testpdf content", MimetypeMap.MIMETYPE_PDF);
String uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=false";
GetRequest req = new GetRequest(uri);
Response res = sendRequest(req, 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId();
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testhtml.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=false";
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId();
res = sendRequest(new GetRequest(uri), 200);
assertNull(res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
uri = URL_CONTENT_DOWNLOAD + testpdf.getId() + "?a=true";
res = sendRequest(new GetRequest(uri), 200);
assertEquals("attachment", res.getHeader("Content-Disposition"));
assertEquals(MimetypeMap.MIMETYPE_PDF + ";charset=UTF-8", res.getContentType());
}
public NodeRef createNodeWithTextContent(NodeRef parentNode, String nodeCmName, QName nodeType, String content, String mimetype)
{
NodeRef nodeRef = createNode(parentNode, nodeCmName, nodeType);
@@ -146,7 +184,7 @@ public class ContentGetTest extends BaseWebScriptTest
if (content != null)
{
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.setMimetype(mimetype);
writer.setEncoding("UTF-8");
writer.putContent(content);
}

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.web.util;
import java.io.BufferedReader;
@@ -32,6 +32,7 @@ import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Date;
import javax.servlet.ServletContext;
@@ -44,7 +45,8 @@ import org.alfresco.util.TempFileProvider;
import org.alfresco.util.WebApplicationContextLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
import org.springframework.beans.BeanUtils;
@@ -145,6 +147,8 @@ public abstract class AbstractJettyComponent implements JettyComponent
configureWebAppContext(webAppContext);
ignoreAmbiguousLinks(server);
server.start();
if(logger.isDebugEnabled())
@@ -203,15 +207,27 @@ public abstract class AbstractJettyComponent implements JettyComponent
}
}
});
// with a login-config in web.xml, jetty seems to require this in order to start successfully
webAppContext.getSecurityHandler().setLoginService(new HashLoginService());
// arbitrary temporary file location
File tmp = new File(TempFileProvider.getSystemTempDir(), String.valueOf(System.currentTimeMillis()));
webAppContext.setResourceBase(tmp.getAbsolutePath());
}
/**
* In newer jetty versions there is a stricter check for links e.g. "//" is not allowed, which clashes
* with some of our tests, because even a NodeRef triggers it - "workspace://..."
* Since Jetty is only used in tests it's alright to block this behaviour.
*
* @param server
*/
private void ignoreAmbiguousLinks(Server server) {
Arrays.stream(server.getConnectors())
.flatMap(c -> c.getConnectionFactories().stream())
.filter(cf -> cf instanceof HttpConnectionFactory)
.map(cf -> (HttpConnectionFactory) cf)
.forEach(hcf -> hcf.getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986));
}
public void shutdown()
{
try

View File

@@ -26,9 +26,11 @@
package org.alfresco.rest.api;
import org.alfresco.rest.api.impl.RulesImplTest;
import org.alfresco.rest.api.impl.rules.NodeValidatorTest;
import org.alfresco.rest.api.impl.rules.RuleSetsImplTest;
import org.alfresco.rest.api.model.rules.ActionTest;
import org.alfresco.rest.api.model.rules.CompositeConditionTest;
import org.alfresco.rest.api.impl.rules.RulesImplTest;
import org.alfresco.rest.api.model.rules.RuleTest;
import org.alfresco.rest.api.model.rules.SimpleConditionTest;
import org.alfresco.rest.api.nodes.NodeRulesRelationTest;
@@ -41,6 +43,8 @@ import org.junit.runners.Suite;
@Suite.SuiteClasses({
NodeRulesRelationTest.class,
RulesImplTest.class,
RuleSetsImplTest.class,
NodeValidatorTest.class,
RuleTest.class,
ActionTest.class,
SimpleConditionTest.class,

View File

@@ -1,667 +0,0 @@
/*
* #%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 java.util.Collections.emptyList;
import static org.alfresco.rest.api.model.rules.RuleSet.DEFAULT_ID;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.AccessStatus.DENIED;
import static org.alfresco.service.cmr.security.PermissionService.CHANGE_PERMISSIONS;
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.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import junit.framework.TestCase;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.Rule;
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;
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.Action;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.security.PermissionService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RulesImplTest extends TestCase
{
private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final String RULE_ID = "dummy-rule-id";
private static final NodeRef folderNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
private static final NodeRef ruleSetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
private static final NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
private static final Paging paging = Paging.DEFAULT;
private static final Action action = new ActionImpl(folderNodeRef, "actionId", "actionDefinitionName");
private static final String RULE_NAME = "Rule name";
@Mock
private Nodes nodesMock;
@Mock
private PermissionService permissionServiceMock;
@Mock
private RuleService ruleServiceMock;
@InjectMocks
private RulesImpl rules;
@Before
@Override
public void setUp() throws Exception
{
MockitoAnnotations.openMocks(this);
given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
given(nodesMock.nodeMatches(any(), any(), any())).willReturn(true);
given(permissionServiceMock.hasReadPermission(any())).willReturn(ALLOWED);
given(permissionServiceMock.hasPermission(any(), any())).willReturn(ALLOWED);
}
@Test
public void testGetRules()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.getRules(any())).willReturn(List.of(createRule(RULE_ID)));
// when
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().getRules(folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rulesPage)
.isNotNull()
.extracting(CollectionWithPagingInfo::getCollection)
.isNotNull()
.extracting(Collection::size)
.isEqualTo(1);
assertThat(rulesPage.getCollection().stream().findFirst().orElse(null))
.isNotNull()
.extracting(Rule::getId)
.isEqualTo(RULE_ID);
}
@Test
public void testGetRulesForDefaultRuleSet()
{
given(ruleServiceMock.getRuleSetNode(any())).willReturn(ruleSetNodeRef);
given(ruleServiceMock.getRules(any())).willReturn(List.of(createRule(RULE_ID)));
// when
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, DEFAULT_ID, paging);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().getRules(folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rulesPage)
.isNotNull()
.extracting(CollectionWithPagingInfo::getCollection)
.isNotNull()
.extracting(Collection::size)
.isEqualTo(1);
assertThat(rulesPage.getCollection().stream().findFirst().orElse(null))
.isNotNull()
.extracting(Rule::getId)
.isEqualTo(RULE_ID);
}
@Test
public void testGetRulesForNotExistingFolderNode()
{
given(nodesMock.nodeMatches(eq(folderNodeRef), any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testGetRulesForNotExistingRuleSetNode()
{
given(nodesMock.nodeMatches(eq(folderNodeRef), any(), any())).willReturn(true);
given(nodesMock.nodeMatches(eq(ruleSetNodeRef), any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testGetRulesForNotExistingDefaultRuleSetNode()
{
given(nodesMock.nodeMatches(eq(folderNodeRef), any(), any())).willReturn(true);
given(ruleServiceMock.getRuleSetNode(folderNodeRef)).willReturn(null);
// when
assertThatExceptionOfType(RelationshipResourceNotFoundException.class).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, DEFAULT_ID, paging));
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testGetRulesForNotAssociatedRuleSetToFolder()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testGetRulesWithoutReadPermission()
{
given(permissionServiceMock.hasReadPermission(any())).willReturn(DENIED);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testGetRuleById()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(true);
given(ruleServiceMock.getRule(any())).willReturn(createRule(RULE_ID));
// when
final Rule rule = rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().getRule(ruleNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rule)
.isNotNull()
.extracting(Rule::getId)
.isEqualTo(RULE_ID);
}
@Test
public void testGetRuleByIdForDefaultRuleSet()
{
final String defaultRuleSetId = "-default-";
given(ruleServiceMock.getRuleSetNode(any())).willReturn(ruleSetNodeRef);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(true);
given(ruleServiceMock.getRule(any())).willReturn(createRule(RULE_ID));
// when
final Rule rule = rules.getRuleById(FOLDER_NODE_ID, defaultRuleSetId, RULE_ID);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().getRule(ruleNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rule)
.isNotNull()
.extracting(Rule::getId)
.isEqualTo(RULE_ID);
}
@Test
public void testGetRuleByIdForNotAssociatedRuleToRuleSet()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
/** Create a single rule. */
@Test
public void testSaveRules()
{
Rule ruleBody = mock(Rule.class);
List<Rule> ruleList = List.of(ruleBody);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
given(serviceRule.getAction()).willReturn(action);
// when
List<Rule> actual = rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList);
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(Rule.from(serviceRule, false));
assertThat(actual).isEqualTo(expected);
}
/** Check that when passing the default rule set then we don't perform any validation around the rule set node. */
@Test
public void testSaveRules_defaultRuleSet()
{
Rule ruleBody = mock(Rule.class);
List<Rule> ruleList = List.of(ruleBody);
org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
given(ruleServiceMock.getRuleSetNode(any())).willReturn(ruleSetNodeRef);
org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
given(serviceRule.getAction()).willReturn(action);
// when
List<Rule> actual = rules.createRules(folderNodeRef.getId(), DEFAULT_ID, ruleList);
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(Rule.from(serviceRule, false));
assertThat(actual).isEqualTo(expected);
}
@Test
public void testSaveRules_ruleSetNotAssociatedWithFolder()
{
Rule rule = Rule.builder().name(RULE_NAME).create();
List<Rule> ruleList = List.of(rule);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef)).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testSaveRules_emptyRuleList()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
List<Rule> ruleList = emptyList();
// when
List<Rule> actual = this.rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList);
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(actual).isEqualTo(emptyList());
}
/** Create three rules in a single call and check they are all passed to the RuleService. */
@Test
public void testSaveRules_createMultipleRules()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
List<Rule> ruleBodyList = new ArrayList<>();
List<Rule> expected = new ArrayList<>();
for (String ruleId : List.of("A", "B", "C"))
{
Rule ruleBody = mock(Rule.class);
ruleBodyList.add(ruleBody);
org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, ruleId);
given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
given(serviceRule.getAction()).willReturn(action);
expected.add(Rule.from(serviceRule, false));
}
// when
List<Rule> actual = rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleBodyList);
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
for (Rule ruleBody : ruleBodyList)
{
then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
}
then(ruleServiceMock).should(times(ruleBodyList.size())).isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(actual).isEqualTo(expected);
}
/** Try to create a rule without CHANGE permission and check an exception is thrown. */
@Test
public void testSaveRules_noChangePermission()
{
given(permissionServiceMock.hasPermission(folderNodeRef, CHANGE_PERMISSIONS)).willReturn(DENIED);
Rule ruleBody = mock(Rule.class);
List<Rule> ruleList = List.of(ruleBody);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() ->
rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
/** Check that we can update a rule. */
@Test
public void testUpdateRules()
{
Rule ruleBody = mock(Rule.class);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef)).willReturn(true);
given(ruleServiceMock.isRuleSetShared(ruleSetNodeRef)).willReturn(true);
org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
given(serviceRule.getAction()).willReturn(action);
// when
Rule updatedRule = rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, ruleBody);
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).should().saveRule(folderNodeRef, serviceRuleBody);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
Rule expected = Rule.builder().id(RULE_ID)
.enabled(true)
.shared(true)
.triggers(emptyList())
.conditions(CompositeCondition.builder().inverted(false).create())
.create();
assertThat(updatedRule).isEqualTo(expected);
}
/** Check that we get an error if the rule set is not a child of the folder. */
@Test
public void testUpdateRules_ruleSetNotInFolder()
{
Rule ruleBody = mock(Rule.class);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef)).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() ->
rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, ruleBody));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
/** Check that we get an error if the rule is not a child of the rule set. */
@Test
public void testUpdateRules_ruleNotInRuleSet()
{
Rule ruleBody = mock(Rule.class);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef)).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() ->
rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, ruleBody));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
/** Try to update a rule without CHANGE permission and check an exception is thrown. */
@Test
public void testUpdateRules_noChangePermission()
{
given(permissionServiceMock.hasPermission(folderNodeRef, CHANGE_PERMISSIONS)).willReturn(DENIED);
Rule ruleBody = mock(Rule.class);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() ->
rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, ruleBody));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById() {
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
org.alfresco.service.cmr.rule.Rule rule = createRule(RULE_ID);
given(ruleServiceMock.getRule(any())).willReturn(rule);
//when
rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).should().getRule(ruleNodeRef);
then(ruleServiceMock).should().removeRule(folderNodeRef, rule);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_NonExistingRuleId() {
given(nodesMock.validateNode(RULE_ID)).willThrow(new EntityNotFoundException(RULE_ID));
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_RuleIdNotInRuleSet() {
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(false);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_NonExistingRuleSetId() {
given(nodesMock.validateNode(RULE_SET_ID)).willThrow(new EntityNotFoundException(RULE_SET_ID));
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_RuleSetNotInFolder() {
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(false);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().nodeMatches(eq(folderNodeRef), any(), isNull());
then(nodesMock).should().nodeMatches(eq(ruleSetNodeRef), any(), isNull());
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_NonExistingFolderId() {
given(nodesMock.validateOrLookupNode(FOLDER_NODE_ID, null)).willThrow(new EntityNotFoundException(RULE_ID));
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
/** Try to delete a rule without CHANGE permission and check an exception is thrown. */
@Test
public void testDeleteRuleById_noChangePermission()
{
given(permissionServiceMock.hasPermission(folderNodeRef, CHANGE_PERMISSIONS)).willReturn(DENIED);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() ->
rules.deleteRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
private static org.alfresco.service.cmr.rule.Rule createRule(final String id) {
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
final org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
rule.setNodeRef(nodeRef);
rule.setRuleType("ruleType");
rule.setAction(action);
return rule;
}
}

View File

@@ -0,0 +1,592 @@
/*
* #%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.rules;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.times;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
import org.alfresco.repo.action.executer.CheckInActionExecuter;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter;
import org.alfresco.repo.action.executer.LinkCategoryActionExecuter;
import org.alfresco.repo.action.executer.MoveActionExecuter;
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.service.Experimental;
import org.alfresco.service.cmr.action.ActionDefinition;
import org.alfresco.service.cmr.action.ActionService;
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.namespace.NamespaceService;
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 ActionParameterConverterTest
{
private static final String VERSIONABLE = "versionable";
private static final String VERSIONABLE_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + VERSIONABLE;
private static final String CHECKOUT = "checkout";
private static final String CHECKOUT_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CHECKOUT;
private static final String CONTAINS = "contains";
private static final String CONTAINS_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CONTAINS;
private static final String CLASSIFIABLE = "generalclassifiable";
private static final String CLASSIFIABLE_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CLASSIFIABLE;
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";
@Mock
private DictionaryService dictionaryService;
@Mock
private ActionService actionService;
@Mock
private NamespaceService namespaceService;
@Mock
private ActionDefinition actionDefinition;
@Mock
private ParameterDefinition actionDefinitionParam1;
@Mock
private ParameterDefinition actionDefinitionParam2;
@Mock
private ParameterDefinition actionDefinitionParam3;
@Mock
private DataTypeDefinition dataTypeDefinition1;
@Mock
private DataTypeDefinition dataTypeDefinition2;
@Mock
private DataTypeDefinition dataTypeDefinition3;
@InjectMocks
private ActionParameterConverter objectUnderTest;
@Test
public void testAddAspectConversion()
{
final String name = AddFeaturesActionExecuter.NAME;
final String aspectNameKey = AddFeaturesActionExecuter.PARAM_ASPECT_NAME;
final Map<String, Serializable> params = Map.of(aspectNameKey, VERSIONABLE_ASPECT);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(aspectNameKey)).willReturn(actionDefinitionParam1);
final QName qname = DataTypeDefinition.QNAME;
given(actionDefinitionParam1.getType()).willReturn(qname);
given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(aspectNameKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(qname);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).should().getNamespaceURI(any());
then(namespaceService).shouldHaveNoMoreInteractions();
final Serializable convertedParam = convertedParams.get(aspectNameKey);
assertTrue(convertedParam instanceof QName);
assertEquals(VERSIONABLE, ((QName) convertedParam).getLocalName());
assertEquals(VERSIONABLE_ASPECT, ((QName) convertedParam).getPrefixString());
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedParam).getNamespaceURI());
}
@Test
public void testCopyConversion()
{
final String name = CopyActionExecuter.NAME;
final String destinationFolderKey = CopyActionExecuter.PARAM_DESTINATION_FOLDER;
final String deepCopyKey = CopyActionExecuter.PARAM_DEEP_COPY;
final Map<String, Serializable> params = Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID, deepCopyKey, true);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
given(actionDefinition.getParameterDefintion(deepCopyKey)).willReturn(actionDefinitionParam2);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(nodeRef);
final QName bool = DataTypeDefinition.BOOLEAN;
given(actionDefinitionParam2.getType()).willReturn(bool);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition2);
given(dataTypeDefinition2.getJavaClassName()).willReturn(Boolean.class.getName());
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
then(actionDefinition).should().getParameterDefintion(deepCopyKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should(times(2)).getDataType(bool);
then(dictionaryService).should().getDataType(nodeRef);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).shouldHaveNoInteractions();
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());
final Serializable convertedDeepCopyParam = convertedParams.get(deepCopyKey);
assertThat(convertedDeepCopyParam instanceof Boolean).isTrue();
assertTrue(((Boolean) convertedDeepCopyParam));
}
@Test
public void testExecuteScriptConversion()
{
final String name = ScriptActionExecuter.NAME;
final String executeScriptKey = ScriptActionExecuter.PARAM_SCRIPTREF;
final Map<String, Serializable> params = Map.of(executeScriptKey, DUMMY_SCRIPT_NODE_ID);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(executeScriptKey)).willReturn(actionDefinitionParam1);
final QName scriptNodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(scriptNodeRef);
given(dictionaryService.getDataType(scriptNodeRef)).willReturn(dataTypeDefinition1);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(executeScriptKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(scriptNodeRef);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).shouldHaveNoInteractions();
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());
}
@Test
public void testMoveConversion()
{
final String name = MoveActionExecuter.NAME;
final String destinationFolderKey = MoveActionExecuter.PARAM_DESTINATION_FOLDER;
final Map<String, Serializable> params = Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(nodeRef);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(nodeRef);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).shouldHaveNoInteractions();
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());
}
@Test
public void testCheckInConversion()
{
final String name = CheckInActionExecuter.NAME;
final String descriptionKey = CheckInActionExecuter.PARAM_DESCRIPTION;
final String minorChangeKey = CheckInActionExecuter.PARAM_MINOR_CHANGE;
String description = "dummy description";
final Map<String, Serializable> params = Map.of(descriptionKey, description, minorChangeKey, true);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(descriptionKey)).willReturn(actionDefinitionParam1);
given(actionDefinition.getParameterDefintion(minorChangeKey)).willReturn(actionDefinitionParam2);
final QName text = DataTypeDefinition.TEXT;
given(actionDefinitionParam1.getType()).willReturn(text);
final QName bool = DataTypeDefinition.BOOLEAN;
given(actionDefinitionParam2.getType()).willReturn(bool);
given(dictionaryService.getDataType(text)).willReturn(dataTypeDefinition1);
given(dataTypeDefinition1.getJavaClassName()).willReturn(String.class.getName());
given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition2);
given(dataTypeDefinition2.getJavaClassName()).willReturn(Boolean.class.getName());
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(descriptionKey);
then(actionDefinition).should().getParameterDefintion(minorChangeKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should(times(2)).getDataType(bool);
then(dictionaryService).should(times(2)).getDataType(text);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).shouldHaveNoInteractions();
final Serializable convertedDescriptionParam = convertedParams.get(descriptionKey);
assertTrue(convertedDescriptionParam instanceof String);
assertEquals(description, convertedDescriptionParam);
final Serializable convertedMinorChangeParam = convertedParams.get(minorChangeKey);
assertTrue(convertedMinorChangeParam instanceof Boolean);
assertTrue((Boolean) convertedMinorChangeParam);
}
@Test
public void testCheckOutConversion()
{
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, DUMMY_FOLDER_NODE_ID, assocNameKey, CHECKOUT_ASPECT, assocTypeKey, CONTAINS_ASPECT);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam1.getType()).willReturn(nodeRef);
given(actionDefinition.getParameterDefintion(assocNameKey)).willReturn(actionDefinitionParam2);
final QName qname = DataTypeDefinition.QNAME;
given(actionDefinitionParam2.getType()).willReturn(qname);
given(actionDefinition.getParameterDefintion(assocTypeKey)).willReturn(actionDefinitionParam3);
given(actionDefinitionParam3.getType()).willReturn(qname);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition2);
given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
then(actionDefinition).should().getParameterDefintion(assocNameKey);
then(actionDefinition).should().getParameterDefintion(assocTypeKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should(times(2)).getDataType(qname);
then(dictionaryService).should().getDataType(nodeRef);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).should(times(2)).getNamespaceURI(any());
then(namespaceService).shouldHaveNoMoreInteractions();
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());
final Serializable convertedAssocNameParam = convertedParams.get(assocNameKey);
assertTrue(convertedAssocNameParam instanceof QName);
assertEquals(CHECKOUT, ((QName) convertedAssocNameParam).getLocalName());
assertEquals(CHECKOUT_ASPECT, ((QName) convertedAssocNameParam).getPrefixString());
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedAssocNameParam).getNamespaceURI());
final Serializable convertedAssocTypeParam = convertedParams.get(assocTypeKey);
assertTrue(convertedAssocTypeParam instanceof QName);
assertEquals(CONTAINS, ((QName) convertedAssocTypeParam).getLocalName());
assertEquals(CONTAINS_ASPECT, ((QName) convertedAssocTypeParam).getPrefixString());
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedAssocTypeParam).getNamespaceURI());
}
@Test
public void testCategoryLinkConversion()
{
final String name = LinkCategoryActionExecuter.NAME;
final String categoryAspectKey = LinkCategoryActionExecuter.PARAM_CATEGORY_ASPECT;
final String categoryValueKey = LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE;
final Map<String, Serializable> params = Map.of(categoryAspectKey, CLASSIFIABLE_ASPECT, categoryValueKey, DUMMY_FOLDER_NODE_ID);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(categoryAspectKey)).willReturn(actionDefinitionParam1);
final QName qname = DataTypeDefinition.QNAME;
given(actionDefinitionParam1.getType()).willReturn(qname);
given(actionDefinition.getParameterDefintion(categoryValueKey)).willReturn(actionDefinitionParam2);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam2.getType()).willReturn(nodeRef);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition2);
given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(categoryAspectKey);
then(actionDefinition).should().getParameterDefintion(categoryValueKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(qname);
then(dictionaryService).should().getDataType(nodeRef);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).should().getNamespaceURI(any());
then(namespaceService).shouldHaveNoMoreInteractions();
final Serializable convertedCatValueParam = convertedParams.get(categoryAspectKey);
assertTrue(convertedCatValueParam instanceof QName);
assertEquals(CLASSIFIABLE, ((QName) convertedCatValueParam).getLocalName());
assertEquals(CLASSIFIABLE_ASPECT, ((QName) convertedCatValueParam).getPrefixString());
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());
}
@Test
public void testRemoveAspectConversion()
{
final String name = RemoveFeaturesActionExecuter.NAME;
final String aspectNameKey = RemoveFeaturesActionExecuter.PARAM_ASPECT_NAME;
final Map<String, Serializable> params = Map.of(aspectNameKey, VERSIONABLE_ASPECT);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(aspectNameKey)).willReturn(actionDefinitionParam1);
final QName qname = DataTypeDefinition.QNAME;
given(actionDefinitionParam1.getType()).willReturn(qname);
given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(aspectNameKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(qname);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).should().getNamespaceURI(any());
then(namespaceService).shouldHaveNoMoreInteractions();
final Serializable convertedParam = convertedParams.get(aspectNameKey);
assertTrue(convertedParam instanceof QName);
assertEquals(VERSIONABLE, ((QName) convertedParam).getLocalName());
assertEquals(VERSIONABLE_ASPECT, ((QName) convertedParam).getPrefixString());
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedParam).getNamespaceURI());
}
@Test
public void testAddWorkflowConversion()
{
final String name = SimpleWorkflowActionExecuter.NAME;
final String approveStepKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_STEP;
final String approveFolderKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_FOLDER;
final String approveMoveKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_MOVE;
final String rejectStepKey = SimpleWorkflowActionExecuter.PARAM_REJECT_STEP;
final String rejectFolderKey = SimpleWorkflowActionExecuter.PARAM_REJECT_FOLDER;
final String rejectMoveKey = SimpleWorkflowActionExecuter.PARAM_REJECT_MOVE;
final String approve = "Approve";
final String reject = "Reject";
final Map<String, Serializable> params =
Map.of(approveStepKey, approve, approveFolderKey, DUMMY_FOLDER_NODE_ID, approveMoveKey, true,
rejectStepKey, reject, rejectFolderKey, DUMMY_FOLDER_NODE_ID, rejectMoveKey, true);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(rejectStepKey)).willReturn(actionDefinitionParam1);
given(actionDefinition.getParameterDefintion(approveStepKey)).willReturn(actionDefinitionParam1);
final QName text = DataTypeDefinition.TEXT;
given(actionDefinitionParam1.getType()).willReturn(text, text);
given(actionDefinition.getParameterDefintion(rejectFolderKey)).willReturn(actionDefinitionParam2);
given(actionDefinition.getParameterDefintion(approveFolderKey)).willReturn(actionDefinitionParam2);
final QName nodeRef = DataTypeDefinition.NODE_REF;
given(actionDefinitionParam2.getType()).willReturn(nodeRef, nodeRef);
given(actionDefinition.getParameterDefintion(rejectMoveKey)).willReturn(actionDefinitionParam3);
given(actionDefinition.getParameterDefintion(approveMoveKey)).willReturn(actionDefinitionParam3);
final QName bool = DataTypeDefinition.BOOLEAN;
given(actionDefinitionParam3.getType()).willReturn(bool, bool);
given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
given(dictionaryService.getDataType(text)).willReturn(dataTypeDefinition2);
given(dataTypeDefinition2.getJavaClassName()).willReturn(String.class.getName());
given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition3);
given(dataTypeDefinition3.getJavaClassName()).willReturn(Boolean.class.getName());
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(approveStepKey);
then(actionDefinition).should().getParameterDefintion(approveFolderKey);
then(actionDefinition).should().getParameterDefintion(approveMoveKey);
then(actionDefinition).should().getParameterDefintion(rejectStepKey);
then(actionDefinition).should().getParameterDefintion(rejectFolderKey);
then(actionDefinition).should().getParameterDefintion(rejectMoveKey);
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should(times(4)).getDataType(text);
then(dictionaryService).should(times(2)).getDataType(nodeRef);
then(dictionaryService).should(times(4)).getDataType(bool);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).shouldHaveNoInteractions();
final Serializable convertedApproveStepParam = convertedParams.get(approveStepKey);
assertTrue(convertedApproveStepParam instanceof String);
assertEquals(approve, convertedApproveStepParam);
final Serializable convertedRejectStepParam = convertedParams.get(rejectStepKey);
assertTrue(convertedRejectStepParam instanceof String);
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());
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());
final Serializable convertedApproveMoveParam = convertedParams.get(approveMoveKey);
assertTrue(convertedApproveMoveParam instanceof Boolean);
assertTrue((Boolean) convertedApproveMoveParam);
final Serializable convertedRejectMoveParam = convertedParams.get(rejectMoveKey);
assertTrue(convertedRejectMoveParam instanceof Boolean);
assertTrue((Boolean) convertedRejectMoveParam);
}
@Test
public void testSetPropertyConversion()
{
final String name = SetPropertyValueActionExecuter.NAME;
final String propertyNameKey = SetPropertyValueActionExecuter.PARAM_PROPERTY;
final String propertyValueKey = SetPropertyValueActionExecuter.PARAM_VALUE;
final String propertyTypeKey = "prop_type";
final String dummy_key_value = "dummy_key_value";
final String propType = "d:text";
final Map<String, Serializable> params =
Map.of(propertyNameKey, IDENTIFIER_ASPECT, propertyValueKey, dummy_key_value, propertyTypeKey, propType);
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
given(actionDefinition.getParameterDefintion(propertyNameKey)).willReturn(actionDefinitionParam1);
final QName qname = DataTypeDefinition.QNAME;
given(actionDefinitionParam1.getType()).willReturn(qname);
given(actionDefinition.getParameterDefintion(propertyValueKey)).willReturn(actionDefinitionParam2);
final QName any = DataTypeDefinition.ANY;
given(actionDefinitionParam2.getType()).willReturn(any);
given(actionDefinition.getParameterDefintion(propertyTypeKey)).willReturn(null);
given(actionDefinition.getAdhocPropertiesAllowed()).willReturn(true);
given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
given(dictionaryService.getDataType(any)).willReturn(dataTypeDefinition2);
given(dataTypeDefinition2.getJavaClassName()).willReturn(Object.class.getName());
given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
//when
final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
then(actionService).should().getActionDefinition(name);
then(actionService).shouldHaveNoMoreInteractions();
then(actionDefinition).should().getParameterDefintion(propertyNameKey);
then(actionDefinition).should().getParameterDefintion(propertyValueKey);
then(actionDefinition).should().getParameterDefintion(propertyTypeKey);
then(actionDefinition).should().getAdhocPropertiesAllowed();
then(actionDefinition).shouldHaveNoMoreInteractions();
then(dictionaryService).should().getDataType(qname);
then(dictionaryService).should(times(2)).getDataType(any);
then(dictionaryService).shouldHaveNoMoreInteractions();
then(namespaceService).should().getNamespaceURI(any());
then(namespaceService).shouldHaveNoMoreInteractions();
final Serializable convertedPropNameParam = convertedParams.get(propertyNameKey);
assertTrue(convertedPropNameParam instanceof QName);
assertEquals(IDENTIFIER, ((QName) convertedPropNameParam).getLocalName());
assertEquals(IDENTIFIER_ASPECT, ((QName) convertedPropNameParam).getPrefixString());
assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedPropNameParam).getNamespaceURI());
final Serializable convertedPropValParam = convertedParams.get(propertyValueKey);
assertTrue(convertedPropValParam instanceof String);
assertEquals(dummy_key_value, convertedPropValParam);
final Serializable convertedPropTypeParam = convertedParams.get(propertyTypeKey);
assertTrue(convertedPropTypeParam instanceof String);
assertEquals(propType, convertedPropTypeParam);
}
@Test
public void testQnameServiceModelParamConversion() {
given(namespaceService.getPrefixes(any())).willReturn(List.of("cm"));
final String qname = "{cm-dummy-prefix}audio";
final Serializable qnameParam = QName.createQName(qname);
//when
final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(qnameParam);
then(namespaceService).should().getPrefixes(any());
then(namespaceService).shouldHaveNoMoreInteractions();
assertEquals("cm:audio", convertedParam);
}
@Test
public void testNodeRefServiceModelParamConversion() {
//given
final Serializable nodeRefParam = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_FOLDER_NODE_ID);
//when
final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(nodeRefParam);
then(namespaceService).shouldHaveNoInteractions();
assertEquals(DUMMY_FOLDER_NODE_ID, convertedParam);
}
@Test
public void testOtherServiceModelParamConversion() {
//given
final Serializable dummyStringParam = "dummy-param";
//when
final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(dummyStringParam);
then(namespaceService).shouldHaveNoInteractions();
assertEquals(dummyStringParam, convertedParam);
}
}

View File

@@ -0,0 +1,117 @@
/*
* #%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.rules;
import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
import static org.alfresco.service.cmr.rule.RuleType.OUTBOUND;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.BDDMockito.then;
import java.util.List;
import junit.framework.TestCase;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.CompositeActionImpl;
import org.alfresco.repo.action.RuntimeActionService;
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
import org.alfresco.repo.action.executer.CopyActionExecuter;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.Rule;
import org.assertj.core.api.Assertions;
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 ActionPermissionValidatorTest extends TestCase
{
private static final String DUMMY_NODE_ID = "dummy-node-id";
@Mock
private RuntimeActionService runtimeActionService;
@InjectMocks
private ActionPermissionValidator objectUnderTest;
@Test
public void testPositiveRulePermissionValidation()
{
//given
final CompositeActionImpl compositeAction =
new CompositeActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "composite-id");
final Action action1 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-1",
CopyActionExecuter.NAME);
compositeAction.addAction(action1);
final Action action2 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-2",
CheckOutActionExecuter.NAME);
compositeAction.addAction(action2);
final Rule inputRule = new Rule();
inputRule.setAction(compositeAction);
inputRule.setRuleTypes(List.of(INBOUND));
//when
final Rule validatedRule = objectUnderTest.validateRulePermissions(inputRule);
then(runtimeActionService).should().verifyActionAccessRestrictions(action1);
then(runtimeActionService).should().verifyActionAccessRestrictions(action2);
then(runtimeActionService).shouldHaveNoMoreInteractions();
((CompositeActionImpl) validatedRule.getAction()).getActions()
.forEach(action -> Assertions.assertThat(action.getParameterValue("actionContext")).isEqualTo("rule"));
}
@Test
public void testNegativeRulePermissionValidation()
{
//given
final CompositeActionImpl compositeAction =
new CompositeActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "composite-id");
final Action action1 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-1",
CopyActionExecuter.NAME);
compositeAction.addAction(action1);
final Action action2 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-2",
CheckOutActionExecuter.NAME);
compositeAction.addAction(action2);
final Rule inputRule = new Rule();
inputRule.setAction(compositeAction);
inputRule.setRuleTypes(List.of(OUTBOUND));
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validateRulePermissions(inputRule));
then(runtimeActionService).should().verifyActionAccessRestrictions(action1);
then(runtimeActionService).should().verifyActionAccessRestrictions(action2);
then(runtimeActionService).shouldHaveNoMoreInteractions();
}
}

View File

@@ -0,0 +1,441 @@
/*
* #%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.rules;
import static org.alfresco.model.ContentModel.TYPE_FOLDER;
import static org.alfresco.model.ContentModel.TYPE_SYSTEM_FOLDER;
import static org.alfresco.repo.rule.RuleModel.TYPE_RULE;
import static org.alfresco.rest.api.model.rules.RuleSet.DEFAULT_ID;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import static org.alfresco.service.cmr.security.AccessStatus.DENIED;
import static org.alfresco.service.cmr.security.PermissionService.CHANGE_PERMISSIONS;
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.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.reset;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.Node;
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;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.service.cmr.security.PermissionService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class NodeValidatorTest
{
private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final String RULE_ID = "dummy-rule-id";
private static final String PARENT_NODE_ID = "dummy-parent-node-id";
private static final NodeRef folderNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
private static final NodeRef ruleSetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
private static final NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
private static final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_NODE_ID);
@Mock
private Nodes nodesMock;
@Mock
private Node ruleSetNodeMock;
@Mock
private PermissionService permissionServiceMock;
@Mock
private RuleService ruleServiceMock;
@Mock
private NodeService nodeServiceMock;
@Mock
private ChildAssociationRef primaryParentMock;
@InjectMocks
private NodeValidator nodeValidator;
@Before
public void setUp() throws Exception
{
MockitoAnnotations.openMocks(this);
given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
given(nodesMock.nodeMatches(any(), any(), any())).willReturn(true);
given(permissionServiceMock.hasReadPermission(any())).willReturn(ALLOWED);
given(permissionServiceMock.hasPermission(any(), any())).willReturn(ALLOWED);
}
@Test
public void testValidateFolderNode()
{
// when
final NodeRef nodeRef = nodeValidator.validateFolderNode(FOLDER_NODE_ID, false);
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().nodeMatches(folderNodeRef, Set.of(TYPE_FOLDER), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
assertThat(nodeRef).isNotNull().isEqualTo(folderNodeRef);
}
@Test
public void testValidateFolderNode_notExistingFolder()
{
given(nodesMock.validateOrLookupNode(any(), any())).willThrow(new EntityNotFoundException(FOLDER_NODE_ID));
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> nodeValidator.validateFolderNode(FOLDER_NODE_ID, false));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateFolderNode_notMatchingTypeFolder()
{
given(nodesMock.nodeMatches(any(), eq(Set.of(TYPE_FOLDER)), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> nodeValidator.validateFolderNode(FOLDER_NODE_ID, false));
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
then(nodesMock).should().nodeMatches(folderNodeRef, Set.of(TYPE_FOLDER), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateFolderNode_noReadPermission()
{
given(permissionServiceMock.hasReadPermission(any())).willReturn(DENIED);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(
() -> nodeValidator.validateFolderNode(FOLDER_NODE_ID, false));
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateFolderNode_noChangePermission()
{
given(permissionServiceMock.hasPermission(any(), any())).willReturn(DENIED);
// when
assertThatExceptionOfType(PermissionDeniedException.class).isThrownBy(() ->
nodeValidator.validateFolderNode(folderNodeRef.getId(), true));
then(permissionServiceMock).should().hasPermission(folderNodeRef, CHANGE_PERMISSIONS);
then(permissionServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void validateRuleSetNode()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(true);
// when
final NodeRef nodeRef = nodeValidator.validateRuleSetNode(RULE_SET_ID, folderNodeRef);
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().nodeMatches(ruleSetNodeRef, Set.of(TYPE_SYSTEM_FOLDER), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
assertThat(nodeRef).isNotNull().isEqualTo(ruleSetNodeRef);
}
@Test
public void testValidateRuleSetNodeNoParentId()
{
given(nodesMock.getNode(any())).willReturn(ruleSetNodeMock);
given(nodeServiceMock.getPrimaryParent(any())).willReturn(primaryParentMock);
given(primaryParentMock.getParentRef()).willReturn(parentNodeRef);
//when
final NodeRef nodeRef = nodeValidator.validateRuleSetNode(LINK_TO_NODE_ID,true);
assertThat(nodeRef).isNotNull().isEqualTo(parentNodeRef);
}
@Test
public void validateRuleSetNode_defaultId()
{
given(ruleServiceMock.getRuleSetNode(any())).willReturn(ruleSetNodeRef);
// when
final NodeRef nodeRef = nodeValidator.validateRuleSetNode(DEFAULT_ID, folderNodeRef);
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).shouldHaveNoInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
assertThat(nodeRef).isNotNull().isEqualTo(ruleSetNodeRef);
}
@Test
public void testValidateRuleSetNode_notExistingRuleSet()
{
given(nodesMock.validateNode(RULE_SET_ID)).willThrow(new EntityNotFoundException(RULE_SET_ID));
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> nodeValidator.validateRuleSetNode(RULE_SET_ID, folderNodeRef));
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateRuleSetNode_notMatchingTypeSystemFolder()
{
given(nodesMock.nodeMatches(any(), eq(Set.of(TYPE_SYSTEM_FOLDER)), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> nodeValidator.validateRuleSetNode(RULE_SET_ID, folderNodeRef));
then(nodesMock).should().validateNode(RULE_SET_ID);
then(nodesMock).should().nodeMatches(ruleSetNodeRef, Set.of(TYPE_SYSTEM_FOLDER), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateRuleSetNode_notExistingDefaultRuleSet()
{
given(ruleServiceMock.getRuleSetNode(folderNodeRef)).willReturn(null);
// when
assertThatExceptionOfType(RelationshipResourceNotFoundException.class).isThrownBy(
() -> nodeValidator.validateRuleSetNode(DEFAULT_ID, folderNodeRef));
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(nodesMock).shouldHaveNoInteractions();
}
@Test
public void testValidateRuleSetNode_notAssociatedRuleSetToFolder()
{
given(ruleServiceMock.isRuleSetAssociatedWithFolder(any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> nodeValidator.validateRuleSetNode(RULE_SET_ID, folderNodeRef));
then(ruleServiceMock).should().isRuleSetAssociatedWithFolder(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void validateRuleNode()
{
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(true);
// when
final NodeRef nodeRef = nodeValidator.validateRuleNode(RULE_ID, ruleSetNodeRef);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(ruleNodeRef, Set.of(TYPE_RULE), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
assertThat(nodeRef).isNotNull().isEqualTo(ruleNodeRef);
}
@Test
public void validateRuleNode_nullRuleSet()
{
// when
final NodeRef nodeRef = nodeValidator.validateRuleNode(RULE_ID, null);
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(ruleNodeRef, Set.of(TYPE_RULE), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
then(permissionServiceMock).shouldHaveNoInteractions();
assertThat(nodeRef).isNotNull().isEqualTo(ruleNodeRef);
}
@Test
public void testValidateRuleNode_notExistingRule()
{
given(nodesMock.validateNode(RULE_ID)).willThrow(new EntityNotFoundException(RULE_ID));
//when
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
() -> nodeValidator.validateRuleNode(RULE_ID, ruleSetNodeRef));
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateRuleNode_notMatchingTypeRule()
{
given(nodesMock.nodeMatches(any(), eq(Set.of(TYPE_RULE)), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> nodeValidator.validateRuleNode(RULE_ID, ruleSetNodeRef));
then(nodesMock).should().validateNode(RULE_ID);
then(nodesMock).should().nodeMatches(ruleNodeRef, Set.of(TYPE_RULE), null);
then(nodesMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testValidateRuleNode_notAssociatedRuleToRuleSet()
{
given(ruleServiceMock.isRuleAssociatedWithRuleSet(any(), any())).willReturn(false);
// when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> nodeValidator.validateRuleNode(RULE_ID, ruleSetNodeRef));
then(ruleServiceMock).should().isRuleAssociatedWithRuleSet(ruleNodeRef, ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testIsRuleSetNode()
{
//resetting mock to bypass setup method
resetNodesMock();
boolean actual = nodeValidator.isRuleSetNode(RULE_SET_ID);
Assert.assertTrue(actual);
}
@Test
public void testIsNotRuleSetNode()
{
//resetting mock to bypass setup method
resetNodesMock();
//using an id that doesn't belong to a ruleset node
boolean actual = nodeValidator.isRuleSetNode(FOLDER_NODE_ID);
Assert.assertFalse(actual);
}
@Test
public void testIsRuleSetNotNullAndShared()
{
given(ruleServiceMock.isRuleSetShared(any())).willReturn(true);
// when
final boolean shared = nodeValidator.isRuleSetNotNullAndShared(ruleSetNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(shared).isTrue();
}
@Test
public void testIsRuleSetNotNullAndShared_nullRuleSetNode()
{
// when
final boolean shared = nodeValidator.isRuleSetNotNullAndShared(null);
then(ruleServiceMock).shouldHaveNoInteractions();
assertThat(shared).isFalse();
}
@Test
public void testIsRuleSetNotNullAndShared_withoutRuleSetAndWithFolder()
{
given(ruleServiceMock.getRuleSetNode(any())).willReturn(ruleSetNodeRef);
// when
nodeValidator.isRuleSetNotNullAndShared(null, folderNodeRef);
then(ruleServiceMock).should().getRuleSetNode(folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testIsRuleSetNotNullAndShared_withRuleSetAndWithFolder()
{
// when
nodeValidator.isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
private void resetNodesMock() {
reset(nodesMock);
given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
given(nodesMock.nodeMatches(ruleSetNodeRef, Set.of(ContentModel.TYPE_SYSTEM_FOLDER), null)).willReturn(true);
}
}

View File

@@ -0,0 +1,121 @@
/*
* #%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.rules;
import static java.util.Collections.emptyList;
import static org.alfresco.rest.api.impl.rules.RuleLoader.IS_SHARED;
import static org.alfresco.rest.api.model.rules.RuleTrigger.OUTBOUND;
import static org.alfresco.rest.api.model.rules.RuleTrigger.UPDATE;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.MockitoAnnotations.openMocks;
import java.util.List;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
/** Unit tests for {@link RuleLoader}. */
public class RuleLoaderTest
{
private static final String NODE_ID = "node-id";
private static final NodeRef NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
private static final String TITLE = "title";
private static final String DESCRIPTION = "description";
private static final boolean ENABLED = true;
private static final boolean CASCADE = true;
private static final boolean EXECUTE_ASYNCHRONOUSLY = false;
private static final List<String> TRIGGERS = List.of("update", "outbound");
private static final NodeRef RULE_SET_NODE = new NodeRef("rule://set/");
@InjectMocks
private RuleLoader ruleLoader;
@Mock
private RuleService ruleServiceMock;
@Mock
private NodeValidator nodeValidatorMock;
private org.alfresco.service.cmr.rule.Rule serviceRule = createServiceRule();
@Before
public void setUp()
{
openMocks(this);
}
@Test
public void testLoadRule()
{
Rule rule = ruleLoader.loadRule(serviceRule, emptyList());
Rule expected = Rule.builder().id(NODE_ID)
.name(TITLE)
.description(DESCRIPTION)
.enabled(ENABLED)
.cascade(CASCADE)
.asynchronous(EXECUTE_ASYNCHRONOUSLY)
.triggers(List.of(UPDATE, OUTBOUND)).create();
assertThat(rule).isEqualTo(expected);
}
@Test
public void testLoadRule_noExceptionWithNullInclude()
{
ruleLoader.loadRule(serviceRule, null);
}
@Test
public void testLoadRule_includeIsShared()
{
// Simulate the rule set being shared.
given(ruleServiceMock.getRuleSetNode(NODE_REF)).willReturn(RULE_SET_NODE);
given(nodeValidatorMock.isRuleSetNotNullAndShared(RULE_SET_NODE)).willReturn(true);
Rule rule = ruleLoader.loadRule(serviceRule, List.of(IS_SHARED));
assertThat(rule).extracting("isShared").isEqualTo(true);
}
private org.alfresco.service.cmr.rule.Rule createServiceRule()
{
org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
rule.setNodeRef(NODE_REF);
rule.setTitle(TITLE);
rule.setDescription(DESCRIPTION);
rule.setRuleDisabled(!ENABLED);
rule.applyToChildren(CASCADE);
rule.setExecuteAsynchronously(EXECUTE_ASYNCHRONOUSLY);
rule.setRuleTypes(TRIGGERS);
return rule;
}
}

View File

@@ -0,0 +1,133 @@
/*
* #%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.rules;
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.OWNING_FOLDER;
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;
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
import static org.mockito.BDDMockito.given;
import java.util.List;
import junit.framework.TestCase;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
/** Unit tests for {@link RuleSetLoader}. */
@Experimental
@RunWith (MockitoJUnitRunner.class)
public class RuleSetLoaderTest extends TestCase
{
private static final String FOLDER_ID = "dummy-folder-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final NodeRef FOLDER_NODE = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
private static final NodeRef RULE_SET_NODE = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
private static final String LINKING_FOLDER_ID = "linking-folder";
private static final NodeRef LINKING_FOLDER = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, LINKING_FOLDER_ID);
private static final NodeRef INHERITING_FOLDER = new NodeRef("inheriting://folder/");
@InjectMocks
private RuleSetLoader ruleSetLoader;
@Mock
private NodeService nodeServiceMock;
@Mock
private ChildAssociationRef ruleSetAssociationMock;
@Mock
private ChildAssociationRef linkAssociationMock;
@Before
@Override
public void setUp()
{
given(ruleSetAssociationMock.getParentRef()).willReturn(FOLDER_NODE);
given(nodeServiceMock.getPrimaryParent(RULE_SET_NODE)).willReturn(ruleSetAssociationMock);
given(linkAssociationMock.getParentRef()).willReturn(LINKING_FOLDER);
given(nodeServiceMock.getParentAssocs(RULE_SET_NODE)).willReturn(List.of(ruleSetAssociationMock, linkAssociationMock));
}
@Test
public void testLoadRuleSet_noIncludes()
{
// Call the method under test.
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, null);
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).create();
assertEquals(expected, actual);
}
@Test
public void testLoadRuleSet_includeOwningFolder()
{
// Call the method under test.
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, List.of(OWNING_FOLDER));
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).owningFolder(FOLDER_NODE).create();
assertEquals(expected, actual);
}
@Test
public void testLoadRuleSet_includeInclusionType()
{
// Call the method under test.
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, List.of(INCLUSION_TYPE));
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(OWNED).create();
assertEquals(expected, actual);
}
@Test
public void testLoadRuleSet_linkedInclusionType()
{
// Call the method under test.
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, LINKING_FOLDER, List.of(INCLUSION_TYPE));
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(LINKED).create();
assertEquals(expected, actual);
}
@Test
public void testLoadRuleSet_inheritedInclusionType()
{
// Call the method under test.
RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, INHERITING_FOLDER, List.of(INCLUSION_TYPE));
RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(INHERITED).create();
assertEquals(expected, actual);
}
}

View File

@@ -0,0 +1,236 @@
/*
* #%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.rules;
import static java.util.Collections.emptyList;
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 java.util.Collection;
import java.util.List;
import junit.framework.TestCase;
import org.alfresco.repo.rule.RuleModel;
import org.alfresco.repo.rule.RuntimeRuleService;
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.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
/** Unit tests for {@link RuleSetsImpl}. */
@Experimental
@RunWith (MockitoJUnitRunner.class)
public class RuleSetsImplTest extends TestCase
{
private static final String FOLDER_ID = "dummy-folder-id";
private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final NodeRef FOLDER_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
private static final NodeRef LINK_TO_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, LINK_TO_NODE_ID);
private static final NodeRef RULE_SET_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
private static final Paging PAGING = Paging.DEFAULT;
private static final List<String> INCLUDES = List.of("dummy-includes");
@InjectMocks
private RuleSetsImpl ruleSets;
@Mock
private RuleSetLoader ruleSetLoaderMock;
@Mock
private NodeValidator nodeValidatorMock;
@Mock
private NodeService nodeServiceMock;
@Mock
private RuleService ruleServiceMock;
@Mock
private RuntimeRuleService runtimeRuleServiceMock;
@Mock
private RuleSet ruleSetMock;
@Mock
private ChildAssociationRef assocRef;
@Before
@Override
public void setUp()
{
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.validateFolderNode(eq(FOLDER_ID), anyBoolean())).willReturn(FOLDER_NODE);
given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
given(ruleServiceMock.getRuleSetNode(FOLDER_NODE)).willReturn(RULE_SET_NODE);
given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, INCLUDES)).willReturn(ruleSetMock);
}
@Test
public void testGetRuleSets()
{
// 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().getRuleSetNode(FOLDER_NODE);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
Collection<RuleSet> expected = List.of(ruleSetMock);
assertEquals(expected, actual.getCollection());
assertEquals(PAGING, actual.getPaging());
}
@Test
public void testGetZeroRuleSets()
{
// Simulate no rule sets for the folder.
given(ruleServiceMock.getRuleSetNode(FOLDER_NODE)).willReturn(null);
// 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().getRuleSetNode(FOLDER_NODE);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertEquals(emptyList(), actual.getCollection());
assertEquals(PAGING, actual.getPaging());
}
@Test
public void testGetRuleSetById()
{
// Call the method under test.
RuleSet actual = ruleSets.getRuleSetById(FOLDER_ID, RULE_SET_ID, INCLUDES);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
assertEquals(ruleSetMock, actual);
}
@Test
public void testLinkToFolderRuleSet()
{
NodeRef childNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-child-id");
given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, false);
given(runtimeRuleServiceMock.getSavedRuleFolderAssoc(any(NodeRef.class))).willReturn(assocRef);
given(assocRef.getChildRef()).willReturn(childNodeRef);
//when
String actual = ruleSets.linkToRuleSet(FOLDER_ID,LINK_TO_NODE_ID).getId();
then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
then(ruleServiceMock).should().hasRules(FOLDER_NODE);
then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
then(nodeServiceMock).shouldHaveNoMoreInteractions();
assertEquals(childNodeRef.getId(),actual);
}
@Test
public void testLinkToRuleSet()
{
NodeRef childNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-child-id");
given(nodeValidatorMock.isRuleSetNode(any())).willReturn(true);
given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, false);
given(runtimeRuleServiceMock.getSavedRuleFolderAssoc(any(NodeRef.class))).willReturn(assocRef);
given(assocRef.getChildRef()).willReturn(childNodeRef);
//when
String actual = ruleSets.linkToRuleSet(FOLDER_ID,LINK_TO_NODE_ID).getId();
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).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
then(ruleServiceMock).should().hasRules(FOLDER_NODE);
then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
then(nodeServiceMock).shouldHaveNoMoreInteractions();
assertEquals(childNodeRef.getId(),actual);
}
@Test
public void testLinkToRuleSet_targetFolderHasNoRules()
{
given(ruleServiceMock.hasRules(LINK_TO_NODE)).willReturn(false);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> ruleSets.linkToRuleSet(FOLDER_ID, LINK_TO_NODE_ID)
);
then(nodeServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(runtimeRuleServiceMock).shouldHaveNoInteractions();
}
@Test
public void testLinkToRuleSet_folderShouldntHavePreExistingRules()
{
given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, true);
//when
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
() -> ruleSets.linkToRuleSet(FOLDER_ID, LINK_TO_NODE_ID));
then(nodeServiceMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
then(ruleServiceMock).should().hasRules(FOLDER_NODE);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(runtimeRuleServiceMock).shouldHaveNoInteractions();
}
}

View File

@@ -0,0 +1,145 @@
/*
* #%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.rules;
import static java.util.Collections.emptyMap;
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
import static org.alfresco.rest.api.model.rules.RuleSetting.IS_INHERITANCE_ENABLED_KEY;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
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 junit.framework.TestCase;
import org.alfresco.rest.api.model.rules.RuleSetting;
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
/** Unit tests for {@link RuleSettingsImpl}. */
@Experimental
@RunWith (MockitoJUnitRunner.class)
public class RuleSettingsImplTest extends TestCase
{
private static final String FOLDER_ID = "dummy-folder-id";
private static final NodeRef FOLDER_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
@InjectMocks
private RuleSettingsImpl ruleSettings;
@Mock
private NodeValidator nodeValidatorMock;
@Mock
private NodeService nodeServiceMock;
@Before
@Override
public void setUp()
{
given(nodeValidatorMock.validateFolderNode(eq(FOLDER_ID), anyBoolean())).willReturn(FOLDER_NODE);
}
@Test
public void testGetRuleSetting_disabled()
{
given(nodeServiceMock.hasAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES)).willReturn(true);
// Call the method under test.
RuleSetting ruleSetting = ruleSettings.getRuleSetting(FOLDER_ID, IS_INHERITANCE_ENABLED_KEY);
RuleSetting expected = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(false).create();
assertEquals(expected, ruleSetting);
}
@Test
public void testGetRuleSetting_enabled()
{
given(nodeServiceMock.hasAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES)).willReturn(false);
// Call the method under test.
RuleSetting ruleSetting = ruleSettings.getRuleSetting(FOLDER_ID, IS_INHERITANCE_ENABLED_KEY);
RuleSetting expected = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(true).create();
assertEquals(expected, ruleSetting);
}
@Test
public void testGetRuleSetting_unrecognisedKey()
{
assertThatExceptionOfType(NotFoundException.class)
.isThrownBy(() -> ruleSettings.getRuleSetting(FOLDER_ID, "-fakeSetting-"));
}
@Test
public void testSetRuleSetting_enable()
{
RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(true).create();
// Call the method under test.
RuleSetting actual = ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting);
assertEquals(ruleSetting, actual);
then(nodeServiceMock).should().removeAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES);
}
@Test
public void testSetRuleSetting_disable()
{
RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(false).create();
// Call the method under test.
RuleSetting actual = ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting);
assertEquals(ruleSetting, actual);
then(nodeServiceMock).should().addAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES, emptyMap());
}
@Test
public void testSetRuleSetting_unrecognisedKey()
{
RuleSetting ruleSetting = RuleSetting.builder().key("-fakeSetting-").value(true).create();
assertThatExceptionOfType(NotFoundException.class)
.isThrownBy(() -> ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting));
}
@Test
public void testSetRuleSetting_nonBooleanValue()
{
RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(123456).create();
assertThatExceptionOfType(IllegalArgumentException.class)
.isThrownBy(() -> ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting));
}
}

View File

@@ -0,0 +1,628 @@
/*
* #%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.rules;
import static java.util.Collections.emptyList;
import static org.alfresco.rest.api.model.rules.RuleSet.DEFAULT_ID;
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.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import java.io.Serializable;
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.CompositeActionImpl;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.rules.Rule;
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;
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.CompositeAction;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RulesImplTest extends TestCase
{
private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final String RULE_ID = "dummy-rule-id";
private static final NodeRef FOLDER_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
private static final NodeRef RULE_SET_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
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 String ACTION_DEFINITION_NAME = "actionDefinitionName";
private static final Map<String, Serializable> DUMMY_PARAMS = Map.of("dummy-key", "dummy-value");
@Mock
private Nodes nodesMock;
@Mock
private NodeValidator nodeValidatorMock;
@Mock
private RuleService ruleServiceMock;
@Mock
private RuleLoader ruleLoaderMock;
@Mock
private ActionParameterConverter actionParameterConverterMock;
@Mock
private ActionPermissionValidator actionPermissionValidatorMock;
@Mock
private org.alfresco.service.cmr.rule.Rule serviceRuleMock;
@Mock
private Rule ruleMock;
private org.alfresco.service.cmr.rule.Rule ruleModel = createRule(RULE_ID);
private CompositeAction compositeAction = new CompositeActionImpl(RULE_NODE_REF, "compositeActionId");
@InjectMocks
private RulesImpl rules;
@Before
@Override
public void setUp() throws Exception
{
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
given(nodeValidatorMock.validateRuleNode(any(), any())).willReturn(RULE_NODE_REF);
given(ruleServiceMock.getRule(RULE_NODE_REF)).willReturn(ruleModel);
given(ruleServiceMock.getRules(FOLDER_NODE_REF)).willReturn(List.of(ruleModel));
given(ruleLoaderMock.loadRule(ruleModel, INCLUDE)).willReturn(ruleMock);
compositeAction.addAction(new ActionImpl(FOLDER_NODE_REF, "actionId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
}
@Test
public void testGetRules()
{
given(ruleLoaderMock.loadRule(ruleModel, emptyList())).willReturn(ruleMock);
// when
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
then(ruleLoaderMock).shouldHaveNoMoreInteractions();
assertThat(rulesPage)
.isNotNull()
.extracting(CollectionWithPagingInfo::getCollection)
.isNotNull()
.extracting(Collection::size)
.isEqualTo(1);
assertThat(rulesPage.getCollection().stream().findFirst().get()).isEqualTo(ruleMock);
}
@Test
public void testGetRules_emptyResult()
{
given(ruleServiceMock.getRules(any())).willReturn(emptyList());
// when
final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rulesPage)
.isNotNull()
.extracting(CollectionWithPagingInfo::getCollection)
.isNotNull()
.extracting(Collection::isEmpty)
.isEqualTo(true);
}
@Test
public void testGetRules_invalidFolder()
{
for (Exception exception : folderValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testGetRules_invalidRuleSet()
{
for (Exception exception : ruleSetValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testGetRuleById()
{
// when
final Rule rule = rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(nodesMock).shouldHaveNoInteractions();
then(ruleServiceMock).should().getRule(RULE_NODE_REF);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(rule).isEqualTo(ruleMock);
}
@Test
public void testGetRuleById_invalidFolder()
{
for (Exception exception : folderValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testGetRuleById_invalidRuleSet()
{
for (Exception exception : ruleSetValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testGetRuleById_invalidRule()
{
for (Exception exception : ruleValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
/**
* Create a single rule.
*/
@Test
public void testCreateRules()
{
List<Rule> ruleList = List.of(ruleMock);
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
given(serviceRuleMock.getAction()).willReturn(compositeAction);
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
// when
List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleList, INCLUDE);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(ruleMock);
assertThat(actual).isEqualTo(expected);
}
/**
* Check that when passing the default rule set then we don't perform any validation around the rule set node.
*/
@Test
public void testCreateRules_defaultRuleSet()
{
List<Rule> ruleList = List.of(ruleMock);
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
given(serviceRuleMock.getAction()).willReturn(compositeAction);
given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
// when
List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), DEFAULT_ID, ruleList, INCLUDE);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
then(ruleServiceMock).shouldHaveNoMoreInteractions();
List<Rule> expected = List.of(ruleMock);
assertThat(actual).isEqualTo(expected);
}
@Test
public void testCreateRules_emptyRuleList()
{
List<Rule> ruleList = emptyList();
// when
List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleList, INCLUDE);
then(ruleServiceMock).shouldHaveNoInteractions();
assertThat(actual).isEqualTo(emptyList());
}
/**
* Create three rules in a single call and check they are all passed to the RuleService.
*/
@Test
public void testCreateRules_createMultipleRules()
{
List<Rule> ruleBodyList = new ArrayList<>();
List<Rule> expected = new ArrayList<>();
IntStream.range(0, 3).forEach(i -> {
Rule ruleBodyMock = mock(Rule.class);
ruleBodyList.add(ruleBodyMock);
org.alfresco.service.cmr.rule.Rule serviceRuleMockInner = mock(org.alfresco.service.cmr.rule.Rule.class);
given(ruleBodyMock.toServiceModel(nodesMock)).willReturn(serviceRuleMockInner);
final CompositeAction compositeActionInner = new CompositeActionImpl(RULE_NODE_REF, "compositeActionInnerId");
compositeActionInner.addAction(new ActionImpl(FOLDER_NODE_REF, "actionInnerId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
given(serviceRuleMockInner.getAction()).willReturn(compositeActionInner);
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMockInner)).willAnswer(arg -> arg.getArguments()[1]);
Rule ruleMockInner = mock(Rule.class);
given(ruleLoaderMock.loadRule(serviceRuleMockInner, INCLUDE)).willReturn(ruleMockInner);
expected.add(ruleMockInner);
given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
});
// when
List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleBodyList, INCLUDE);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
for (Rule ruleBody : ruleBodyList)
{
then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock));
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock));
}
then(actionParameterConverterMock).should(times(3)).getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoMoreInteractions();
assertThat(actual).isEqualTo(expected);
}
@Test
public void testCreateRules_invalidFolder()
{
for (Exception exception : folderValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), emptyList(), INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testCreateRules_invalidRuleSet()
{
for (Exception exception : ruleSetValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), emptyList(), INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
/**
* Check that we can update a rule.
*/
@Test
public void testUpdateRuleById()
{
given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(a -> a.getArguments()[1]);
given(serviceRuleMock.getAction()).willReturn(compositeAction);
given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
// when
Rule updatedRule = rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, ruleMock, INCLUDE);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, serviceRuleMock);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
assertThat(updatedRule).isEqualTo(ruleMock);
}
@Test
public void testUpdateRuleById_invalidFolder()
{
for (Exception exception : folderValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testUpdateRuleById_invalidRuleSet()
{
for (Exception exception : ruleSetValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testUpdateRuleById_invalidRule()
{
for (Exception exception : ruleValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testDeleteRuleById()
{
//when
rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(nodesMock).shouldHaveNoInteractions();
then(ruleServiceMock).should().getRule(RULE_NODE_REF);
then(ruleServiceMock).should().removeRule(FOLDER_NODE_REF, ruleModel);
then(ruleServiceMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteRuleById_invalidFolder()
{
for (Exception exception : folderValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testDeleteRuleById_invalidRuleSet()
{
for (Exception exception : ruleSetValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
@Test
public void testDeleteRuleById_invalidRule()
{
for (Exception exception : ruleValidationExceptions())
{
Mockito.reset(nodeValidatorMock);
given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
// when
assertThatExceptionOfType(exception.getClass()).isThrownBy(
() -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
then(nodeValidatorMock).shouldHaveNoMoreInteractions();
then(ruleServiceMock).shouldHaveNoInteractions();
}
}
private static org.alfresco.service.cmr.rule.Rule createRule(final String id)
{
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
final org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
rule.setNodeRef(nodeRef);
rule.setRuleType("ruleType");
return rule;
}
private static List<Exception> folderValidationExceptions()
{
return List.of(
new EntityNotFoundException(FOLDER_NODE_ID),
new InvalidArgumentException(),
new PermissionDeniedException()
);
}
private static List<Exception> ruleSetValidationExceptions()
{
return List.of(
new EntityNotFoundException(RULE_SET_ID),
new InvalidArgumentException(),
new RelationshipResourceNotFoundException(RULE_SET_ID, "fake-relationship-id")
);
}
private static List<Exception> ruleValidationExceptions()
{
return List.of(
new EntityNotFoundException(RULE_ID),
new InvalidArgumentException(),
new RelationshipResourceNotFoundException(RULE_ID, "fake-relationship-id")
);
}
}

View File

@@ -27,6 +27,8 @@
package org.alfresco.rest.api.model.rules;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import java.util.Collections;
import java.util.List;
@@ -34,15 +36,18 @@ import java.util.List;
import org.alfresco.repo.action.ActionConditionImpl;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.action.executer.ScriptActionExecuter;
import org.alfresco.rest.api.Nodes;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.rule.RuleType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class RuleTest
{
private static final String RULE_ID = "fake-rule-id";
@@ -52,6 +57,7 @@ public class RuleTest
private static final boolean RULE_CASCADE = true;
private static final boolean RULE_ASYNC = true;
private static final boolean RULE_SHARED = true;
private static final String ACTION_DEFINITION_NAME = "action-def-name";
private static final String ERROR_SCRIPT = "error-script-ref";
@Test
@@ -61,7 +67,7 @@ public class RuleTest
final Rule expectedRule = createRuleWithDefaultValues();
// when
final Rule actualRule = Rule.from(ruleModel, RULE_SHARED);
final Rule actualRule = Rule.from(ruleModel);
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
@@ -74,12 +80,57 @@ public class RuleTest
final Rule expectedRule = Rule.builder().enabled(true).create();
// when
final Rule actualRule = Rule.from(ruleModel, false);
final Rule actualRule = Rule.from(ruleModel);
assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
}
@Test
public void testToServiceModel()
{
final Nodes nodesMock = mock(Nodes.class);
final Rule rule = createRuleWithDefaultValues();
rule.setActions(List.of(Action.builder().actionDefinitionId(ACTION_DEFINITION_NAME).create()));
final org.alfresco.service.cmr.rule.Rule expectedRuleModel = createRuleModel();
final org.alfresco.service.cmr.action.Action expectedCompensatingActionModel = createCompensatingActionModel();
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
then(nodesMock).shouldHaveNoMoreInteractions();
assertThat(actualRuleModel)
.isNotNull()
.usingRecursiveComparison().ignoringFields("nodeRef", "action")
.isEqualTo(expectedRuleModel);
assertThat(actualRuleModel.getAction())
.isNotNull();
assertThat(actualRuleModel.getAction().getCompensatingAction())
.isNotNull()
.usingRecursiveComparison().ignoringFields("id")
.isEqualTo(expectedCompensatingActionModel);
}
@Test
public void testToServiceModel_withNullValues()
{
final Nodes nodesMock = mock(Nodes.class);
final Rule rule = new Rule();
final org.alfresco.service.cmr.rule.Rule expectedRuleModel = new org.alfresco.service.cmr.rule.Rule();
expectedRuleModel.setRuleDisabled(true);
// when
final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
then(nodesMock).shouldHaveNoInteractions();
assertThat(actualRuleModel)
.isNotNull()
.usingRecursiveComparison()
.ignoringFields("ruleTypes")
.isEqualTo(expectedRuleModel);
}
private static org.alfresco.service.cmr.rule.Rule createRuleModel() {
final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule(nodeRef);
@@ -89,17 +140,27 @@ public class RuleTest
ruleModel.applyToChildren(RULE_CASCADE);
ruleModel.setExecuteAsynchronously(RULE_ASYNC);
ruleModel.setRuleTypes(List.of(RuleType.INBOUND, RuleType.UPDATE));
final Action compensatingAction = new ActionImpl(nodeRef, "compensatingActionId", "compensatingActionDefName");
compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
final ActionCondition actionCondition = new ActionConditionImpl("actionConditionId", "actionConditionDefName");
final Action action = new ActionImpl(nodeRef, "actionId", "actionDefName");
action.setCompensatingAction(compensatingAction);
action.addActionCondition(actionCondition);
ruleModel.setAction(action);
ruleModel.setAction(createActionModel());
return ruleModel;
}
private static org.alfresco.service.cmr.action.Action createActionModel() {
final ActionCondition actionCondition = new ActionConditionImpl("action-condition-id", "action-condition-def-name");
final org.alfresco.service.cmr.action.Action actionModel = new ActionImpl(null, "action-id", ACTION_DEFINITION_NAME);
actionModel.setCompensatingAction(createCompensatingActionModel());
actionModel.addActionCondition(actionCondition);
return actionModel;
}
private static org.alfresco.service.cmr.action.Action createCompensatingActionModel() {
final org.alfresco.service.cmr.action.Action compensatingActionModel = new ActionImpl(null, "compensating-action-id", ScriptActionExecuter.NAME);
compensatingActionModel.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
return compensatingActionModel;
}
private static Rule createRuleWithDefaultValues() {
return Rule.builder()
.id(RULE_ID)
@@ -108,7 +169,6 @@ public class RuleTest
.enabled(RULE_ENABLED)
.cascade(RULE_CASCADE)
.asynchronous(RULE_ASYNC)
.shared(RULE_SHARED)
.triggers(List.of(RuleTrigger.INBOUND, RuleTrigger.UPDATE))
.errorScript(ERROR_SCRIPT)
.conditions(CompositeCondition.from(Collections.emptyList()))

View File

@@ -0,0 +1,75 @@
/*
* #%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 junit.framework.TestCase;
import org.alfresco.rest.api.RuleSets;
import org.alfresco.rest.api.model.rules.RuleSetLink;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.List;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NodeRuleSetsRelationTest extends TestCase
{
private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
@Mock
private RuleSets ruleSets;
@Mock
private Parameters parameters;
@InjectMocks
private NodeRuleSetLinksRelation nodeRuleSetLinksRelation;
@Test
public void shouldProperlyCreateLink()
{
RuleSetLink ruleSetLink = new RuleSetLink();
List<RuleSetLink> ruleResult = List.of(ruleSetLink);
RuleSetLink requestBody = new RuleSetLink();
requestBody.setId(LINK_TO_NODE_ID);
when(ruleSets.linkToRuleSet(FOLDER_NODE_ID, LINK_TO_NODE_ID)).thenReturn(ruleSetLink);
List<RuleSetLink> actual = nodeRuleSetLinksRelation.create(FOLDER_NODE_ID,List.of(requestBody), parameters);
Assert.assertEquals(ruleResult, actual);
}
}

View File

@@ -26,6 +26,10 @@
package org.alfresco.rest.api.nodes;
import static org.mockito.BDDMockito.then;
import java.util.List;
import junit.framework.TestCase;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.framework.resource.parameters.Paging;
@@ -40,17 +44,15 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.then;
@Experimental
@RunWith(MockitoJUnitRunner.class)
public class NodeRulesRelationTest extends TestCase
{
private static final String FOLDER_NODE_ID = "dummy-node-id";
private static final String RULE_SET_ID = "dummy-rule-set-id";
private static final String RULE_ID = "dummy-rule-id";
private static final List<String> INCLUDE = List.of("include-field");
private static final Paging PAGING = Paging.DEFAULT;
@Mock
private Rules rulesMock;
@@ -68,35 +70,34 @@ public class NodeRulesRelationTest extends TestCase
@Test
public void testReadAll()
{
final Paging paging = Paging.DEFAULT;
final Parameters parameters = ParamsExtender.valueOf(paging, FOLDER_NODE_ID, RULE_SET_ID, null);
final Parameters parameters = ParamsExtender.valueOf(PAGING, FOLDER_NODE_ID, RULE_SET_ID, null, INCLUDE);
// when
nodeRulesRelation.readAll(FOLDER_NODE_ID, parameters);
then(rulesMock).should().getRules(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(paging));
then(rulesMock).should().getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
then(rulesMock).shouldHaveNoMoreInteractions();
}
@Test
public void testReadById()
{
final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
// when
nodeRulesRelation.readById(FOLDER_NODE_ID, RULE_SET_ID, parameters);
then(rulesMock).should().getRuleById(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(RULE_ID));
then(rulesMock).should().getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
then(rulesMock).shouldHaveNoMoreInteractions();
}
@Test
public void testDeleteById() {
final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
// when
nodeRulesRelation.delete(FOLDER_NODE_ID, RULE_SET_ID, parameters);
then(rulesMock).should().deleteRuleById(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(RULE_ID));
then(rulesMock).should().deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
then(rulesMock).shouldHaveNoMoreInteractions();
}
}

View File

@@ -1,34 +1,30 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.tests;
import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* Manages an embedded jetty server, hooking it up to the repository spring context and providing
* authenticated, tenant-based access through the tenant servlet.
@@ -42,15 +38,4 @@ public class EnterpriseJettyComponent extends PublicApiJettyComponent
{
super(port, contextPath, configLocations, classLocations);
}
@Override
protected void configureWebAppContext(WebAppContext webAppContext)
{
super.configureWebAppContext(webAppContext);
// the tenant servlet with alfresco managed authentication
ServletHolder servletHolder = new ServletHolder(CmisAtomPubServlet.class);
servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler");
webAppContext.addServlet(servletHolder, "/cmisatom/*");
}
}

View File

@@ -123,7 +123,7 @@ public class ModulePackagesApiTest extends AbstractBaseApiTest
assertNotNull(response);
assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode());
assertEquals("no-cache", response.getHeaders().get("Cache-Control"));
assertEquals("application/json;charset=UTF-8", response.getHeaders().get("Content-Type"));
assertEquals("application/json;charset=utf-8", response.getHeaders().get("Content-Type"));
PublicApiClient.ExpectedErrorResponse errorResponse = RestApiUtil.parseErrorResponse(response.getJsonResponse());
assertNotNull(errorResponse);

View File

@@ -3721,6 +3721,50 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
getSingle(getNodeContentUrl(contentNodeId), null, null, headers, 304);
}
/**
* Tests download of file/content name.
* <p>GET:</p>
* {@literal <host>:<port>/alfresco/api/-default-/public/alfresco/versions/1/nodes/<nodeId>/content}
*/
@Test
public void testDownloadFileContentName() throws Exception
{
setRequestContext(user1);
//
// Test plain text
//
String fileName = "Test Download (1).txt";
File file = getResourceFile(fileName);
MultiPartBuilder multiPartBuilder = MultiPartBuilder.create()
.setFileData(new FileData(fileName, file));
MultiPartRequest reqBody = multiPartBuilder.build();
// Upload text content
HttpResponse response = post(getNodeChildrenUrl(Nodes.PATH_MY), reqBody.getBody(), null, reqBody.getContentType(), 201);
Document document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
String contentNodeId = document.getId();
// Check the upload response
assertEquals(fileName, document.getName());
ContentInfo contentInfo = document.getContent();
assertNotNull(contentInfo);
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, contentInfo.getMimeType());
// Download text content - by default with Content-Disposition header
response = getSingle(NodesEntityResource.class, contentNodeId + "/content", null, 200);
String textContent = response.getResponse();
assertEquals("The quick brown fox jumps over the lazy dog", textContent);
Map<String, String> responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals("attachment; filename=\"Test Download (1).txt\"; filename*=UTF-8''Test%20Download%20%281%29.txt", responseHeaders.get("Content-Disposition"));
}
/**
* Tests download of file/content using backed temp file for streaming.
* <p>

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.tests;
import org.alfresco.repo.web.util.AbstractJettyComponent;
@@ -48,63 +48,16 @@ public class PublicApiJettyComponent extends AbstractJettyComponent
@Override
protected void configureWebAppContext(WebAppContext webAppContext)
{
// ServletContext servletContext = webAppContext.getServletContext();
// the tenant servlet with alfresco managed authentication
ServletHolder servletHolder = new ServletHolder(PublicApiWebScriptServlet.class);
servletHolder.setInitParameter("authenticator", "publicapi.authenticator");
webAppContext.addServlet(servletHolder, "/" + publicApiServletName + "/*");
// DependencyInjectedFilter apiFilter = (DependencyInjectedFilter)getApplicationContext().getBean("publicAPICMISFilter");
// BeanProxyFilter filter = new BeanProxyFilter(servletContext, apiFilter);
// FilterHolder filterHolder = new FilterHolder(filter);
// webAppContext.addFilter(filterHolder, "/" + publicApiServletName + "/*", null);
// the tenant servlet with alfresco managed authentication
servletHolder = new ServletHolder(CmisAtomPubServlet.class);
servletHolder.setInitParameter("callContextHandler", "org.apache.chemistry.opencmis.server.shared.BasicAuthCallContextHandler");
webAppContext.addServlet(servletHolder, "/cmisatom/*");
webAppContext.addServlet(servletHolder, "/cmisatom/*");
}
// private static class BeanProxyFilter implements Filter
// {
// private DependencyInjectedFilter filter;
// private ServletContext context;
//
// private BeanProxyFilter(ServletContext context, DependencyInjectedFilter filter)
// {
// this.context = context;
// this.filter = filter;
// }
//
// /**
// * Initialize the filter.
// *
// * @param args
// * FilterConfig
// * @throws ServletException
// * the servlet exception
// * @exception ServletException
// */
// public void init(FilterConfig args) throws ServletException
// {
// }
//
// /* (non-Javadoc)
// * @see javax.servlet.Filter#destroy()
// */
// public void destroy()
// {
// this.filter = null;
// }
//
// /* (non-Javadoc)
// * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
// */
// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
// ServletException
// {
// this.filter.doFilter(this.context, request, response, chain);
// }
// }
}

View File

@@ -303,7 +303,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
Map<String, String> responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(file1_MimeType+";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(file1_MimeType+";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get("Expires"));
assertEquals("attachment; filename=\"" + fileName1 + "\"; filename*=UTF-8''" + fileName1 + "", responseHeaders.get("Content-Disposition"));
String lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);
@@ -319,7 +319,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(file1_MimeType+";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(file1_MimeType+";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
assertNotNull(responseHeaders.get("Expires"));
assertNull(responseHeaders.get("Content-Disposition"));
@@ -330,7 +330,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertArrayEquals(content2Text.getBytes(), response.getResponseAsBytes());
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(file2_MimeType+";charset=ISO-8859-1", responseHeaders.get("Content-Type"));
assertEquals(file2_MimeType+";charset=iso-8859-1", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get("Expires"));
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
assertEquals("attachment; filename=\"" + fileName2 + "\"; filename*=UTF-8''" + fileName2 + "", responseHeaders.get("Content-Disposition"));
@@ -392,7 +392,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertTrue(response.getResponseAsBytes().length > 0);
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG+";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG+";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
assertNotNull(responseHeaders.get("Expires"));
String docName = "doclib";
@@ -405,7 +405,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertTrue(response.getResponseAsBytes().length > 0);
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG+";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG+";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get("Expires"));
assertNull(responseHeaders.get("Content-Disposition"));
lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);
@@ -816,7 +816,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
Map<String, String> responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(file1_MimeType + ";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(file1_MimeType + ";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get("Expires"));
assertEquals("attachment; filename=\"" + fileName1 + "\"; filename*=UTF-8''" + fileName1 + "", responseHeaders.get("Content-Disposition"));
String lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);
@@ -832,7 +832,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(file1_MimeType + ";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(file1_MimeType + ";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
assertNotNull(responseHeaders.get("Expires"));
assertNull(responseHeaders.get("Content-Disposition"));
@@ -888,7 +888,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertTrue(response.getResponseAsBytes().length > 0);
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
assertNotNull(responseHeaders.get("Expires"));
String docName = "doclib";
@@ -901,7 +901,7 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
assertTrue(response.getResponseAsBytes().length > 0);
responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=UTF-8", responseHeaders.get("Content-Type"));
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=utf-8", responseHeaders.get("Content-Type"));
assertNotNull(responseHeaders.get("Expires"));
assertNull(responseHeaders.get("Content-Disposition"));
lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);

View File

@@ -28,6 +28,7 @@ package org.alfresco.rest.framework.tests.core;
import static org.mockito.Mockito.mock;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter;
@@ -72,4 +73,9 @@ public class ParamsExtender extends Params
{
return new ParamsExtender(entityId, relationshipId, relationship2Id, null, null, null, new Params.RecognizedParams(null, paging, null, null, null, null, null, null, false));
}
public static Params valueOf(Paging paging, String entityId, String relationshipId, String relationship2Id, List<String> include)
{
return new ParamsExtender(entityId, relationshipId, relationship2Id, null, null, null, new Params.RecognizedParams(null, paging, null, null, include, null, null, null, false));
}
}

View File

@@ -0,0 +1 @@
The quick brown fox jumps over the lazy dog

View File

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

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.repo.exporter;
import java.io.IOException;
@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.MLPropertyInterceptor;
@@ -77,6 +78,7 @@ import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.lang3.math.NumberUtils;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.extensions.surf.util.ParameterCheck;
@@ -99,6 +101,8 @@ public class ExporterComponent
private DescriptorService descriptorService;
private AuthenticationService authenticationService;
private PermissionService permissionService;
private String exportChunkSize;
/** Indent Size */
@@ -178,6 +182,14 @@ public class ExporterComponent
{
this.exportSecondaryNodes = exportSecondaryNodes;
}
/**
* @param exportChunkSize the exportChunkSize
*/
public void setExportChunkSize(String exportChunkSize)
{
this.exportChunkSize = exportChunkSize;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ExporterService#exportView(java.io.OutputStream, org.alfresco.service.cmr.view.ExporterCrawlerParameters, org.alfresco.service.cmr.view.Exporter)
@@ -943,28 +955,23 @@ public class ExporterComponent
try
{
// Current strategy is to determine if node is a child of the root exported node
for (NodeRef exportRoot : context.getExportList())
if (context.getExportMap() != null)
{
if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true)
for (NodeRef[] listNodeRef : context.getExportMap().values())
{
// node to export is the root export node (and root is to be exported)
isWithin = true;
}
else
{
// locate export root in primary parent path of node
Path nodePath = nodeService.getPath(nodeRef);
for (int i = nodePath.size() - 1; i >= 0; i--)
for (NodeRef exportRoot : listNodeRef)
{
Path.ChildAssocElement pathElement = (Path.ChildAssocElement) nodePath.get(i);
if (pathElement.getRef().getChildRef().equals(exportRoot))
{
isWithin = true;
break;
}
isWithin = checkIsWithin(nodeRef, exportRoot, parameters);
}
}
}
else
{
for (NodeRef exportRoot : context.getExportList())
{
isWithin = checkIsWithin(nodeRef, exportRoot, parameters);
}
}
}
catch (AccessDeniedException accessErr)
{
@@ -979,6 +986,28 @@ public class ExporterComponent
}
}
private boolean checkIsWithin(NodeRef nodeRef, NodeRef exportRoot, ExporterCrawlerParameters parameters){
if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true)
{
// node to export is the root export node (and root is to be exported)
return true;
}
else
{
// locate export root in primary parent path of node
Path nodePath = nodeService.getPath(nodeRef);
for (int i = nodePath.size() - 1; i >= 0; i--)
{
Path.ChildAssocElement pathElement = (Path.ChildAssocElement) nodePath.get(i);
if (pathElement.getRef().getChildRef().equals(exportRoot))
{
return true;
}
}
}
return false;
}
/**
* Exporter Context
@@ -986,7 +1015,9 @@ public class ExporterComponent
private class ExporterContextImpl implements ExporterContext
{
private NodeRef[] exportList;
private Map<Integer,NodeRef[]> exportListMap;
private NodeRef[] parentList;
private Map<Integer,NodeRef[]> parentListMap;
private String exportedBy;
private Date exportedDate;
private String exporterVersion;
@@ -995,8 +1026,10 @@ public class ExporterComponent
private Map<Integer, Set<NodeRef>> nodesWithAssociations = new HashMap<Integer, Set<NodeRef>>();
private int index;
private int indexSubList;
private int chunkSize;
/**
* Construct
*
@@ -1005,7 +1038,17 @@ public class ExporterComponent
public ExporterContextImpl(ExporterCrawlerParameters parameters)
{
index = 0;
indexSubList = 0;
if(!NumberUtils.isParsable(exportChunkSize)){
chunkSize = 10;
}
else
{
chunkSize = Integer.parseInt(exportChunkSize);
}
// get current user performing export
String currentUserName = authenticationService.getCurrentUserName();
exportedBy = (currentUserName == null) ? "unknown" : currentUserName;
@@ -1022,24 +1065,80 @@ public class ExporterComponent
NodeRef exportOf = getNodeRef(parameters.getExportFrom());
exportList[0] = exportOf;
}
parentList = new NodeRef[exportList.length];
for (int i = 0; i < exportList.length; i++)
if(exportList.length > chunkSize)
{
parentList[i] = getParent(exportList[i], parameters.isCrawlSelf());
exportListMap = splitArray(exportList);
parentListMap = new HashMap<>();
for(Map.Entry<Integer, NodeRef[]> exportEntrySet : exportListMap.entrySet())
{
parentList= new NodeRef[exportEntrySet.getValue().length];
for (int i = 0; i < exportEntrySet.getValue().length; i++)
{
parentList[i] = getParent(exportEntrySet.getValue()[i], parameters.isCrawlSelf());
}
parentListMap.put(exportEntrySet.getKey(), parentList);
}
}
else{
parentList = new NodeRef[exportList.length];
for (int i = 0; i < exportList.length; i++)
{
parentList[i] = getParent(exportList[i], parameters.isCrawlSelf());
}
}
// get exporter version
exporterVersion = descriptorService.getServerDescriptor().getVersion();
}
public Map<Integer, NodeRef[]> splitArray(NodeRef[] arrayToSplit){
if(chunkSize <= 0){
return null;
}
int rest = arrayToSplit.length % chunkSize;
int chunks = arrayToSplit.length / chunkSize + (rest > 0 ? 1 : 0);
Map<Integer, NodeRef[]> arrays = new HashMap<>() ;
for(Integer i = 0; i < (rest > 0 ? chunks - 1 : chunks); i++){
arrays.put(i, Arrays.copyOfRange(arrayToSplit, i * chunkSize, i * chunkSize + chunkSize));
}
if(rest > 0){
arrays.put(chunks - 1, Arrays.copyOfRange(arrayToSplit, (chunks - 1) * chunkSize, (chunks - 1) * chunkSize + rest));
}
return arrays;
}
public boolean canRetrieve()
{
return index < exportList.length;
if(exportListMap != null)
{
if (exportListMap.containsKey(indexSubList))
{
return index < exportListMap.get(indexSubList).length;
}
else
{
return false;
}
}
else {
return index < exportList.length;
}
}
public int setNextValue()
{
return ++index;
if(exportListMap != null && (index == exportListMap.get(indexSubList).length-1)){
resetContext();
if(indexSubList <= exportListMap.size())
{
++indexSubList;
}
}
else{
++index;
}
return index;
}
public void resetContext()
@@ -1078,7 +1177,13 @@ public class ExporterComponent
{
if (canRetrieve())
{
return exportList[index];
if(exportListMap!=null)
{
return exportListMap.get(indexSubList)[index];
}
else {
return exportList[index];
}
}
return null;
}
@@ -1091,7 +1196,13 @@ public class ExporterComponent
{
if (canRetrieve())
{
return parentList[index];
if(parentListMap!=null)
{
return parentListMap.get(indexSubList)[index];
}
else {
return parentList[index];
}
}
return null;
}
@@ -1105,6 +1216,11 @@ public class ExporterComponent
return exportList;
}
public Map<Integer, NodeRef[]> getExportMap()
{
return exportListMap;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ExporterContext#getExportParentList()

View File

@@ -1,31 +1,32 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 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%
*/
/*
* #%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.service.cmr.view;
import java.util.Date;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -73,6 +74,8 @@ public interface ExporterContext
* @return NodeRef[]
*/
public NodeRef[] getExportList();
public Map<Integer, NodeRef[]> getExportMap();
/**
* Gets list of parents for exporting nodes

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