Compare commits

...

282 Commits

Author SHA1 Message Date
Travis CI User
ba7be5999b [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-30 09:49:48 +00:00
Travis CI User
8503b2c96c [maven-release-plugin][skip ci] prepare release 20.27 2022-11-30 09:49:45 +00:00
rrajoria
f43806b9f4 Updating googledrive version 2022-11-30 14:00:25 +05:30
brijmohan1
1eebb8ec12 Feature/RM-7178 Event apis swagger (#1572)
* Added Events Management Section in Swagger

* Removed Events Management Section in Swagger

* RM-7178 swagger implementation for event APIs.

* RM-7178 event API swagger header description .

* RM-7178 event API swagger header description .

* RM-7178 updated create event API description .

* Updated Swagger for Event Management

* RM-7178 updated put and create event API description and body.

* Added /event-type endpoint

* Addressed review comments

* RM-7178 updated swagger for review comments.

* RM-7178 updated swagger for review comments.

* RM-7178 updated swagger for review comments.

* Addressed review comments

* Addressed review comments

* RM-7178 added changes for swagger review comments.

* RM-7178 added changes for swagger review comments.

* RM-7178 added changes for pagination in event and event type.

* Addressed review comments

* Addressed review comments

* Addressed review comments (Added 400 response code for paging GET APIs)

* Addressed review comments

* Addressed review comments

* Addressed review comments

* Addressed review comments

* Addressed review comments

* Addressed review comments

Co-authored-by: suneet-gupta <Suneet.Gupta@contractor.alfresco.com>
Co-authored-by: suneet-gupta <suneet.gupta@hyland.com>
2022-11-28 21:45:56 +05:30
Travis CI User
008b340851 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-27 00:11:03 +00:00
Travis CI User
6d3e249149 [maven-release-plugin][skip ci] prepare release 20.26 2022-11-27 00:11:00 +00:00
Alfresco CI User
bf276c60d6 [force] Force release for 2022-11-27. 2022-11-27 00:03:19 +00:00
Travis CI User
54be23513a [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-25 13:54:15 +00:00
Travis CI User
fa0fdff8d4 [maven-release-plugin][skip ci] prepare release 20.25 2022-11-25 13:54:12 +00:00
kcichonczyk
c37b26e678 [ACS-4053] updated INSIGHT_ENGINE_TAG and SOLR tag to 2.0.5.1 (#1578) 2022-11-25 14:17:20 +01:00
Travis CI User
b5e13e253a [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-24 16:27:05 +00:00
Travis CI User
5b5164420f [maven-release-plugin][skip ci] prepare release 20.24 2022-11-24 16:27:02 +00:00
George Evangelopoulos
17c09efb93 ACS-4064: fix for linking from a folder with inherited rules (#1577)
* ACS-4064: fix for linking from a folder with inherited rules

* ACS-4064: fix failing tests and add E2E
2022-11-24 15:48:27 +00:00
Travis CI User
f96304bd28 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-24 14:20:41 +00:00
Travis CI User
499f679c8c [maven-release-plugin][skip ci] prepare release 20.23 2022-11-24 14:20:38 +00:00
Piotr Żurek
80c6a0127d MNT-22686 Load template from the classpath (#1576) 2022-11-24 14:40:13 +01:00
Travis CI User
74e44acb1c [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-23 18:24:44 +00:00
Travis CI User
f4d66debea [maven-release-plugin][skip ci] prepare release 20.22 2022-11-23 18:24:41 +00:00
George Evangelopoulos
af838043c9 ACS-3964: fix for non-inheritable rules still appearing in inherited rule sets (#1565)
* ACS-3964: fix for non-inheritable rules still appearing in inherited rule sets

* ACS-3964: fix failing E2Es and add negative test
2022-11-23 16:24:15 +00:00
Travis CI User
1245647a9f [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-23 15:48:46 +00:00
Travis CI User
fe35f312bb [maven-release-plugin][skip ci] prepare release 20.21 2022-11-23 15:48:43 +00:00
Kacper Magdziarz
a5f16f1b11 Fix/mnt 22686 allow complex rest action params (#1569)
* MNT-22686 Allow more complex action params

* MNT-22686 Add email template test

Co-authored-by: pzurek <Piotr.Zurek@hyland.com>
Co-authored-by: Sara Aspery <sara.aspery@alfresco.com>
2022-11-23 15:11:48 +00:00
Sbisht19
38a9f6d3e1 Merge pull request #1531 from Alfresco/feature/APPS-1722
Feature/apps 1722
2022-11-23 14:12:02 +05:30
sbisht
dc512e5ab0 Merge remote-tracking branch 'origin/feature/APPS-1722' into feature/APPS-1722 2022-11-22 11:54:24 +05:30
sbisht
5c8db99231 updated FileVersionAsRecordRuleTest and FileAsRecordRuleTest [ags] 2022-11-22 11:53:37 +05:30
ashiva
e39a97ed8d "MoveToRuleOnFoldersTest changed names from E and NE to ELECTRONIC AND NON-ELECTRONIC RECORDS"[ags] 2022-11-22 06:07:53 +00:00
Travis CI User
ad0ad081c6 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-20 00:10:49 +00:00
Travis CI User
8b9513ca8f [maven-release-plugin][skip ci] prepare release 20.20 2022-11-20 00:10:46 +00:00
Alfresco CI User
5b3582c051 [force] Force release for 2022-11-20. 2022-11-20 00:03:27 +00:00
Travis CI User
ccba1768bd [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-18 09:49:39 +00:00
Travis CI User
fde8ff084b [maven-release-plugin][skip ci] prepare release 20.19 2022-11-18 09:49:36 +00:00
rrajoria
93a7790d44 MNT-23204: Group Search (#1558) 2022-11-18 14:39:27 +05:30
ashiva
f03790e278 "MoveToRuleOnFoldersTest Completed With Creation of updateMetaData method and declration of variables to global scope"[ags] 2022-11-17 13:00:40 +00:00
ashiva
2c979ea71e "MoveToRuleOnFoldersTest Completed Refactor of code left"[ags] 2022-11-17 11:57:09 +00:00
ashiva
227c74a8bd Merge remote-tracking branch 'origin/feature/APPS-1722' into feature/APPS-1722 2022-11-16 13:56:30 +00:00
ashiva
24aa64c165 "MoveToRuleOnFoldersTest initial changes made"[ags] 2022-11-16 13:55:47 +00:00
cchandan
183873166c Added FileAsRecordRuleTests [ags] 2022-11-16 16:57:24 +05:30
Travis CI User
6e4bb33fb1 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-16 11:02:27 +00:00
Travis CI User
ae37c9273f [maven-release-plugin][skip ci] prepare release 20.18 2022-11-16 11:02:24 +00:00
evasques
783efca1d2 MNT-23108 - Manage contentStream resource closure in RemoteTransformerClient request (#1559)
* Manage contentStream resource closure so we don't have connections hanging when we lose connection to AIO
2022-11-16 10:14:55 +00:00
sbisht
1c9419d635 updated CopyToRuleOnFoldersTest [ags] 2022-11-16 11:47:27 +05:30
Travis CI User
03f80ace94 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-15 14:54:44 +00:00
Travis CI User
e2a62cf315 [maven-release-plugin][skip ci] prepare release 20.17 2022-11-15 14:54:40 +00:00
dependabot[bot]
1cd7253f76 Bump mockito-core from 4.8.1 to 4.9.0 (#1557)
Bumps [mockito-core](https://github.com/mockito/mockito) from 4.8.1 to 4.9.0.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v4.8.1...v4.9.0)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 15:15:00 +01:00
sbisht
17b04d7321 updated FileVersionAsRecordRuleTest [ags] 2022-11-15 16:38:12 +05:30
sbisht
fe5faa3263 updated CopyToRuleOnFoldersTest [ags] 2022-11-15 12:16:44 +05:30
Travis CI User
85e2d84add [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-14 14:03:07 +00:00
Travis CI User
7e7d86aca8 [maven-release-plugin][skip ci] prepare release 20.16 2022-11-14 14:03:05 +00:00
dependabot[bot]
6eab9d2cfb Bump email from 1.9 to 1.11 (#1408)
Bumps [email](https://github.com/Alfresco/alfresco-tas-email) from 1.9 to 1.11.
- [Release notes](https://github.com/Alfresco/alfresco-tas-email/releases)
- [Changelog](https://github.com/Alfresco/alfresco-tas-email/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/Alfresco/alfresco-tas-email/compare/v1.9...v1.11)

---
updated-dependencies:
- dependency-name: org.alfresco.tas:email
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 13:25:07 +00:00
dependabot[bot]
5588cc45a2 Bump maven-jar-plugin from 3.2.2 to 3.3.0 (#1406)
Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.2.2 to 3.3.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.2.2...maven-jar-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 13:24:45 +00:00
Travis CI User
b32da2af76 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-14 10:04:07 +00:00
Travis CI User
ee912bf126 [maven-release-plugin][skip ci] prepare release 20.15 2022-11-14 10:04:04 +00:00
dependabot[bot]
38c638b0ce Bump dependency.jackson.version from 2.14.0-rc1 to 2.14.0 (#1539)
Bumps `dependency.jackson.version` from 2.14.0-rc1 to 2.14.0.

Updates `jackson-core` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson-core/releases)
- [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.14.0-rc1...jackson-core-2.14.0)

Updates `jackson-databind` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson/releases)
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `jackson-datatype-joda` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson-datatype-joda/releases)
- [Commits](https://github.com/FasterXML/jackson-datatype-joda/compare/jackson-datatype-joda-2.14.0-rc1...jackson-datatype-joda-2.14.0)

Updates `jackson-dataformat-yaml` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson-dataformats-text/releases)
- [Commits](https://github.com/FasterXML/jackson-dataformats-text/compare/jackson-dataformats-text-2.14.0-rc1...jackson-dataformats-text-2.14.0)

Updates `jackson-annotations` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson/releases)
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `jackson-module-jaxb-annotations` from 2.14.0-rc1 to 2.14.0
- [Release notes](https://github.com/FasterXML/jackson-modules-base/releases)
- [Commits](https://github.com/FasterXML/jackson-modules-base/compare/jackson-modules-base-2.14.0-rc1...jackson-modules-base-2.14.0)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson.core:jackson-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-joda
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.core:jackson-annotations
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: com.fasterxml.jackson.module:jackson-module-jaxb-annotations
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 09:20:05 +00:00
Travis CI User
db2982ea62 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-13 00:09:53 +00:00
Travis CI User
71454395cb [maven-release-plugin][skip ci] prepare release 20.14 2022-11-13 00:09:50 +00:00
Alfresco CI User
9059d5a87b [force] Force release for 2022-11-13. 2022-11-13 00:03:40 +00:00
Travis CI User
71f8784a7e [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-11 17:20:59 +00:00
Travis CI User
088d8f9448 [maven-release-plugin][skip ci] prepare release 20.13 2022-11-11 17:20:57 +00:00
Tom Page
0d43100018 ACS-3975 Disable intermittent test AddFavoritesTests.addFileFavoriteUsingTagId. 2022-11-11 14:19:13 +00:00
dependabot[bot]
93800b6906 Bump dependency.cxf.version from 3.5.3 to 3.5.4 (#1493)
Bumps `dependency.cxf.version` from 3.5.3 to 3.5.4.

Updates `cxf-rt-frontend-jaxws` from 3.5.3 to 3.5.4

Updates `cxf-rt-frontend-jaxrs` from 3.5.3 to 3.5.4

Updates `cxf-rt-rs-client` from 3.5.3 to 3.5.4

Updates `cxf-rt-transports-http` from 3.5.3 to 3.5.4

Updates `cxf-rt-ws-policy` from 3.5.3 to 3.5.4

---
updated-dependencies:
- dependency-name: org.apache.cxf:cxf-rt-frontend-jaxws
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-frontend-jaxrs
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-rs-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-transports-http
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.cxf:cxf-rt-ws-policy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:05:24 +00:00
dependabot[bot]
82f8b938a6 Bump swagger-parser from 1.0.61 to 1.0.63 (#1503)
Bumps [swagger-parser](https://github.com/swagger-api/swagger-parser) from 1.0.61 to 1.0.63.
- [Release notes](https://github.com/swagger-api/swagger-parser/releases)
- [Commits](https://github.com/swagger-api/swagger-parser/compare/v1.0.61...v1.0.63)

---
updated-dependencies:
- dependency-name: io.swagger:swagger-parser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:03:46 +00:00
dependabot[bot]
8727ee18e8 Bump icu4j from 71.1 to 72.1 (#1510)
Bumps [icu4j](https://github.com/unicode-org/icu) from 71.1 to 72.1.
- [Release notes](https://github.com/unicode-org/icu/releases)
- [Commits](https://github.com/unicode-org/icu/commits)

---
updated-dependencies:
- dependency-name: com.ibm.icu:icu4j
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:03:31 +00:00
dependabot[bot]
a688d475dc Bump mockito-core from 4.6.1 to 4.8.1 (#1516)
Bumps [mockito-core](https://github.com/mockito/mockito) from 4.6.1 to 4.8.1.
- [Release notes](https://github.com/mockito/mockito/releases)
- [Commits](https://github.com/mockito/mockito/compare/v4.6.1...v4.8.1)

---
updated-dependencies:
- dependency-name: org.mockito:mockito-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:03:17 +00:00
dependabot[bot]
83b1c323de Bump woodstox-core from 6.3.1 to 6.4.0 in /repository (#1524)
Bumps [woodstox-core](https://github.com/FasterXML/woodstox) from 6.3.1 to 6.4.0.
- [Release notes](https://github.com/FasterXML/woodstox/releases)
- [Commits](https://github.com/FasterXML/woodstox/compare/woodstox-core-6.3.1...woodstox-core-6.4.0)

---
updated-dependencies:
- dependency-name: com.fasterxml.woodstox:woodstox-core
  dependency-type: direct:production
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:01:34 +00:00
dependabot[bot]
e063e1d816 Bump woodstox-core from 6.3.1 to 6.4.0 (#1525)
Bumps [woodstox-core](https://github.com/FasterXML/woodstox) from 6.3.1 to 6.4.0.
- [Release notes](https://github.com/FasterXML/woodstox/releases)
- [Commits](https://github.com/FasterXML/woodstox/compare/woodstox-core-6.3.1...woodstox-core-6.4.0)

---
updated-dependencies:
- dependency-name: com.fasterxml.woodstox:woodstox-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:01:12 +00:00
dependabot[bot]
65c62c7d03 Bump commons-compress from 1.21 to 1.22 (#1528)
Bumps commons-compress from 1.21 to 1.22.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-compress
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:00:45 +00:00
dependabot[bot]
7a6949a059 Bump spring-security-core from 5.7.3 to 5.7.5 (#1529)
Bumps [spring-security-core](https://github.com/spring-projects/spring-security) from 5.7.3 to 5.7.5.
- [Release notes](https://github.com/spring-projects/spring-security/releases)
- [Changelog](https://github.com/spring-projects/spring-security/blob/main/RELEASE.adoc)
- [Commits](https://github.com/spring-projects/spring-security/compare/5.7.3...5.7.5)

---
updated-dependencies:
- dependency-name: org.springframework.security:spring-security-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:00:30 +00:00
dependabot[bot]
1a0e45b6c8 Bump joda-time from 2.11.1 to 2.12.1 (#1530)
Bumps [joda-time](https://github.com/JodaOrg/joda-time) from 2.11.1 to 2.12.1.
- [Release notes](https://github.com/JodaOrg/joda-time/releases)
- [Changelog](https://github.com/JodaOrg/joda-time/blob/main/RELEASE-NOTES.txt)
- [Commits](https://github.com/JodaOrg/joda-time/compare/v2.11.1...v2.12.1)

---
updated-dependencies:
- dependency-name: joda-time:joda-time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 14:00:14 +00:00
dependabot[bot]
1d1dead902 Bump alfresco-greenmail from 6.4 to 6.5 (#1541)
Bumps [alfresco-greenmail](https://github.com/Alfresco/alfresco-greenmail) from 6.4 to 6.5.
- [Release notes](https://github.com/Alfresco/alfresco-greenmail/releases)
- [Commits](https://github.com/Alfresco/alfresco-greenmail/compare/alfresco-greenmail-6.4...alfresco-greenmail-6.5)

---
updated-dependencies:
- dependency-name: org.alfresco:alfresco-greenmail
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 13:56:21 +00:00
dependabot[bot]
6a69b3fd86 Bump junrar from 7.5.3 to 7.5.4 (#1542)
Bumps [junrar](https://github.com/junrar/junrar) from 7.5.3 to 7.5.4.
- [Release notes](https://github.com/junrar/junrar/releases)
- [Changelog](https://github.com/junrar/junrar/blob/master/CHANGELOG.md)
- [Commits](https://github.com/junrar/junrar/compare/v7.5.3...v7.5.4)

---
updated-dependencies:
- dependency-name: com.github.junrar:junrar
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 13:55:54 +00:00
tiagosalvado10
f391cfa38c [MNT-23158] Scripts limits configuration and optimization (#1519) 2022-11-11 10:58:25 +00:00
Travis CI User
fbef1156a8 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-10 15:39:26 +00:00
Travis CI User
5d93c2efd4 [maven-release-plugin][skip ci] prepare release 20.12 2022-11-10 15:39:23 +00:00
Travis CI User
c94807cd8c [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-10 14:34:49 +00:00
Travis CI User
ff979314ae [maven-release-plugin][skip ci] prepare release 20.11 2022-11-10 14:34:46 +00:00
Vítor Moreira
7f6bd86b0c MNT-22485: added missing tables to query (#1547) 2022-11-10 13:53:22 +00:00
Travis CI User
fd2f793722 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-10 05:17:05 +00:00
Travis CI User
489b0058fe [maven-release-plugin][skip ci] prepare release 20.10 2022-11-10 05:17:02 +00:00
Vítor Moreira
14572d328f MNT-22485: audit query with createdAt criteria returns correct totalI… (#1535)
* MNT-22485: audit query with createdAt criteria returns correct totalItems
2022-11-09 15:58:49 +00:00
MohinishSah
759927c37b updated Gdrive Alpha version 2022-11-09 21:09:16 +05:30
Travis CI User
42ef2160ef [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-09 12:09:02 +00:00
Travis CI User
4f561166b7 [maven-release-plugin][skip ci] prepare release 20.9 2022-11-09 12:08:59 +00:00
Antonio Felix
295a8f7ba2 MNT-23276 - The null facet name should be considered (#1540) 2022-11-09 11:31:51 +00:00
Piyush Joshi
fd73ebe45a Merge pull request #1532 from Alfresco/MNT-22353_Cutoff_Handling_of_Records_in_Hold
[MNT-22353]- Removed Hold cases to be processed in DispositionLifecycleJob
2022-11-09 15:21:41 +05:30
pjoshi31
3bbaabd755 [MNT-22353]- Formatting Changes. 2022-11-09 12:48:16 +05:30
sbisht
63b0ff8cf4 Added FileVersionAsRecordRuleTest [ags] 2022-11-09 10:34:29 +05:30
sbisht
15c99b0c10 Merge remote-tracking branch 'origin/feature/APPS-1722' into feature/APPS-1722 2022-11-09 10:33:47 +05:30
sbisht
0f24f453c8 Added FileVersionAsRecordRuleTest [ags] 2022-11-09 10:33:14 +05:30
Travis CI User
ed50b9bb9b [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-08 14:23:32 +00:00
Travis CI User
361a674a19 [maven-release-plugin][skip ci] prepare release 20.8 2022-11-08 14:23:29 +00:00
Kacper Magdziarz
9f839b5372 Feature/acs-3644 Allow multiple docker-copose files (#1533)
* ACS-3644 enable usage of multiple docker-compose files in start-compose.sh
2022-11-08 12:05:15 +01:00
Piyush Joshi
c76d3b99c4 Update DispositionLifecycleJobExecuter.java 2022-11-07 21:25:03 +05:30
Piyush Joshi
4998f19da9 Update DispositionLifecycleJobExecuter.java 2022-11-07 21:24:10 +05:30
Travis CI User
b1340d12ef [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-07 15:10:48 +00:00
Travis CI User
2b79a4489d [maven-release-plugin][skip ci] prepare release 20.7 2022-11-07 15:10:46 +00:00
Maciej Pichura
e41fc6af02 ACS-3855: Add validation for rule condition comparator. (#1538) 2022-11-07 15:31:19 +01:00
pjoshi31
162264a8d7 [MNT-22353]- Added UnitTest Changes. 2022-11-07 18:32:17 +05:30
pjoshi31
a5977fedb2 [MNT-22353]- Removed length condition. 2022-11-07 12:19:27 +05:30
Travis CI User
024e4e072b [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-06 00:10:56 +00:00
Travis CI User
5c33911e5f [maven-release-plugin][skip ci] prepare release 20.6 2022-11-06 00:10:53 +00:00
Alfresco CI User
2a6eb91ebd [force] Force release for 2022-11-06. 2022-11-06 00:03:33 +00:00
Travis CI User
c588b915d5 [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-04 17:05:47 +00:00
Travis CI User
4e2384fd9a [maven-release-plugin][skip ci] prepare release 20.5 2022-11-04 17:05:44 +00:00
Antonio Felix
6071188405 MNT-23276 - Protect from null facet names (#1534) 2022-11-04 16:17:12 +00:00
ashiva
03ce7e37d4 "MoveToRuleOnFoldersTest added metadata update and and copy of records"[ags] 2022-11-04 15:39:08 +00:00
ashiva
1a5740eec1 Merge remote-tracking branch 'origin/feature/APPS-1722' into feature/APPS-1722 2022-11-04 15:33:19 +00:00
ashiva
f55602842d "MoveToRuleOnFoldersTest added metadata update and and copy of records"[ags] 2022-11-04 15:32:37 +00:00
sbisht
7819e29bcc Added FileVersionAsRecordRuleTest [ags] 2022-11-04 16:37:18 +05:30
sbisht
91031ca72a Added FileAsRecordRuleTests [ags] 2022-11-04 15:48:03 +05:30
cchandan
32314480a1 Added FileAsRecordRuleTests [ags] 2022-11-04 15:10:49 +05:30
ashiva
f49b7a393f "MoveToRuleOnFoldersTest added rule and folder creation" 2022-11-04 08:20:04 +00:00
cchandan
d32ba12405 Merge remote-tracking branch 'origin/feature/APPS-1722' into feature/APPS-1722 2022-11-04 13:39:44 +05:30
cchandan
7430c80a41 Added FileAsRecordRuleTests [ags] 2022-11-04 13:39:11 +05:30
pjoshi31
4c2d9ef64d [MNT-22353]- Added comment. 2022-11-03 11:45:49 +05:30
pjoshi31
f71f243b9b [MNT-22353]- Changed variable. 2022-11-03 11:21:07 +05:30
pjoshi31
3f10227c0f [MNT-22353]- Added Streams for filtering frozen nodes. 2022-11-02 18:05:11 +05:30
pjoshi31
a361596512 [MNT-22353]- Added Parallel Streams for filtering frozen nodes. 2022-11-02 16:07:59 +05:30
pjoshi31
4ad2bda8b9 [MNT-22353]- Added debug logs. 2022-11-02 15:37:08 +05:30
pjoshi31
1339dd59a9 [MNT-22353]- Removed Hold cases to be processed. 2022-11-02 14:52:35 +05:30
ashiva
af2c11063b [ags]"MoveToRuleOnFoldersTest converted" 2022-11-02 07:26:06 +00:00
ashiva
0d74540b2b Merge branch 'feature/APPS-1722' of github.com:Alfresco/alfresco-community-repo into feature/APPS-1722 2022-11-02 07:18:54 +00:00
ashiva
d68ceb1a4b [ags]"MoveToRuleOnFoldersTest converted" 2022-11-02 07:06:46 +00:00
shishuraj.bisht
379f65db0d Added copyToRuleOnFoldersTest [ags] 2022-11-01 17:40:07 +05:30
Travis CI User
9dad28ee4d [maven-release-plugin][skip ci] prepare for next development iteration 2022-11-01 09:44:03 +00:00
Travis CI User
308dd9825a [maven-release-plugin][skip ci] prepare release 20.4 2022-11-01 09:44:00 +00:00
MohinishSah
609aa750d6 updated Gdrive version to verify PRODSEC issue 2022-11-01 14:28:39 +05:30
Travis CI User
def0201274 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-31 10:55:52 +00:00
Travis CI User
a7d885c630 [maven-release-plugin][skip ci] prepare release 20.3 2022-10-31 10:55:49 +00:00
kavitshah-gl
3fcbb076a2 feature/APPS-1672 (#1470)
* 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]

* [ags]

* [ags]

* Revert "[ags api]"

This reverts commit 2153eafc0f.

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* DispositionScheduleLinkedRecordsTest class added

* [ags]

* [ags]

* [ags]

* [ags]

* ags

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Added Audit Holds Test

* Added NonElectronicRecordAuditLogTest file

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* [ags]

* Verifying the test cases execution. [ags]

* Revert "Verifying the test cases execution. [ags]"

This reverts commit 4f6b86fac6.

* Cleanup AuditHoldsTest. [ags]

* Fixed Review Comments. [ags]

* [ags]

* Revert "[ags]"

This reverts commit e2b650b82c.

Co-authored-by: sbisht <shishuraj.bisht@globallogic.com>
Co-authored-by: ashiva <aditya.shiva@globallogic.com>
Co-authored-by: omkar.yadav <omkar.yadav@globallogic.com>
2022-10-31 15:34:55 +05:30
Travis CI User
9ab4d29ff6 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-30 00:11:17 +00:00
Travis CI User
1388a76dc7 [maven-release-plugin][skip ci] prepare release 20.2 2022-10-30 00:11:14 +00:00
Alfresco CI User
1944186ef8 [force] Force release for 2022-10-30. 2022-10-30 00:03:44 +00:00
George Evangelopoulos
66ea8c0534 ACS-3699: Add test with broken copy action (#1506)
* ACS-3699: Add test with broken copy action
2022-10-28 09:38:28 +01:00
Vítor Moreira
571f4b121d MNT-22790: exclude rules to be included in ZIP file when downloading … (#1452)
* MNT-22790: exclude rules to be included in ZIP file when downloading a folder
2022-10-27 14:22:36 +01:00
Sara
2f2e7ade80 ACS-3732 Add test for freemarker unsafe method execution (#1508)
* ACS-3732 Add test for freemarker unsafe method execution
2022-10-27 15:12:33 +02:00
Travis CI User
2d69d44049 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-27 12:11:51 +00:00
Travis CI User
6ad58b137e [maven-release-plugin][skip ci] prepare release 20.1 2022-10-27 12:11:47 +00:00
Krystian Dabrowski
4c086751e6 Update Master branch to 7.4.0 2022-10-27 12:26:37 +02:00
Travis CI User
7cb98f2d5d [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-25 13:08:34 +00:00
Travis CI User
55faedde51 [maven-release-plugin][skip ci] prepare release 17.183 2022-10-25 13:08:31 +00:00
Elia Porciani
32a524eb1f Revert "Fix/acs 2699 mandatory modifier (#1472)" (#1520)
[ACS-3854] This reverts commit 75acf5110e.
2022-10-25 14:16:26 +02:00
Travis CI User
105702bf09 [maven-release-plugin][skip ci] prepare for next development iteration 2022-10-24 12:57:27 +00:00
Travis CI User
9e2e00c4a8 [maven-release-plugin][skip ci] prepare release 17.182 2022-10-24 12:57:24 +00:00
krdabrowski
e79eac4fd8 ACS-3689: Release API explorer (Final) 7.3.0 (#1518) 2022-10-24 14:19:58 +02:00
dependabot[bot]
20f9cfc42d Bump api-explorer from 7.3.0-A1 to 7.3.0 (#1517)
Bumps [api-explorer](https://github.com/Alfresco/rest-api-explorer) from 7.3.0-A1 to 7.3.0.
- [Release notes](https://github.com/Alfresco/rest-api-explorer/releases)
- [Commits](https://github.com/Alfresco/rest-api-explorer/compare/7.3.0-A1...7.3.0)

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

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

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

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

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

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

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

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

* ACS-3652: Fixing failing E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652 E2E tests for script validation.

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

* ACS-3652: Removing unnecessary code.

* ACS-3652 E2Es for link to category action.

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

* ACS-3652: Adding applicable action definition check.

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

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

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

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

* ACS-3652: Small refactoring after code review.

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

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

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

* ACS-3652: Fixing failing E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652: Adding E2E tests.

* ACS-3652 E2E tests for script validation.

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

* ACS-3652: Removing unnecessary code.

* ACS-3652 E2Es for link to category action.

* ACS-3652: Adding applicable action definition check.

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

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

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

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

* ACS-3652: Small refactoring after code review.

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

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

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

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

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

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

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

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

* ACS-3572: Action constraints endpoint fixes.

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

* ACS-3572: Fixing formatting in tests.

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

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3649: Action validators - constraints.

* ACS-3572: Adding validation for extra paramater.

* ACS-3649: Small refactors and fixes.

* ACS-3649: Validations against action definition.

* ACS-3649: Adding @Experimental annotation.

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

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

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

* ACS-3572: Action constraints endpoint fixes.

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

* ACS-3572: Fixing formatting in tests.

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

* ACS-3572: Removing unnecessary code.

* ACS-3572: Removing unnecessary field.

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

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

* ACS-3572: Fixing license headers.

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

* ACS-3649: Bumping tes-restapi version.

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

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

View File

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

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-governance-services-community-parent</artifactId>
<version>17.147</version>
<version>20.28-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.147</version>
<version>20.28-SNAPSHOT</version>
</parent>
<build>

View File

@@ -26,6 +26,7 @@
*/
package org.alfresco.rest.v0;
import static org.apache.http.HttpStatus.SC_OK;
import static org.testng.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
@@ -36,6 +37,7 @@ import java.util.List;
import org.alfresco.rest.core.v0.BaseAPI;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.util.PojoUtility;
import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
@@ -58,6 +60,8 @@ public class RMAuditAPI extends BaseAPI
private static final String RM_AUDIT_API = "{0}rma/admin/rmauditlog";
private static final String RM_AUDIT_LOG_API = RM_AUDIT_API + "?{1}";
private static final String RM_AUDIT_LOG_AS_RECORD = "{0}node/{1}/rmauditlog";
/**
* Returns a list of rm audit entries .
*
@@ -84,6 +88,21 @@ public class RMAuditAPI extends BaseAPI
return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
}
/**
* Returns a list of rm audit entries .
*
* @param user The username of the user to use.
* @param password The password of the user.
* @param size Maximum number of log entries to return
* @return return All return log entries
*/
public List<AuditEntry> getRMAuditLogAll(String user, String password, final int size) {
String parameters = "size=" + size;
JSONArray auditEntries = doGetRequest(user, password,
MessageFormat.format(RM_AUDIT_LOG_API,"{0}", parameters)).getJSONObject("data").getJSONArray("entries");
return PojoUtility.jsonToObject(auditEntries, AuditEntry.class);
}
/**
* Clear the list of audit entries.
*
@@ -100,5 +119,19 @@ public class RMAuditAPI extends BaseAPI
&& getRMAuditLog(username, password, 100, null).size() == 2);
}
/**
* Logs the Audit Log as Record.
*
* @param username The username of the user to use.
* @param password The password of the user.
* @param recNodeRef The Record Node reference for which Audit log should be created as record
* @param destinationNodeRef The Folder id Node reference where the html file should be placed
* @throws AssertionError If the API call didn't create the Audit Log as Record.
*/
public HttpResponse logsAuditLogAsRecord(String username, String password, String recNodeRef, String destinationNodeRef) {
JSONObject requestParams = new JSONObject();
requestParams.put("destination", destinationNodeRef);
return doPostJsonRequest(username, password, SC_OK, requestParams, RM_AUDIT_LOG_AS_RECORD,recNodeRef);
}
}

View File

@@ -97,4 +97,16 @@ public class RecordFoldersAPI extends BaseAPI
return null;
}
public HttpResponse reOpenRecordFolder(String user, String password, String recordFolder)
{
String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordFolder);
JSONObject requestParams = new JSONObject();
requestParams.put("name", "openRecordFolder");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
}

View File

@@ -360,4 +360,25 @@ public class RecordsAPI extends BaseAPI
{
return getNodeRefSpacesStore() + getItemNodeRef(username, password, recordPath + "/" + recordName);
}
/**
* Reopens the record given as parameter
*
* @param user the user declaring the document as record
* @param password the user's password
* @param recordName the record name
* @return The HTTP Response.
*/
public HttpResponse reOpenRecord(String user, String password, String recordName)
{
String recNodeRef = getNodeRefSpacesStore() + contentService.getNodeRef(user, password, RM_SITE_ID, recordName);
JSONObject requestParams = new JSONObject();
requestParams.put("name", "undeclareRecord");
requestParams.put("nodeRef", recNodeRef);
return doPostJsonRequest(user, password, SC_OK, requestParams, RM_ACTIONS_API);
}
}

View File

@@ -0,0 +1,146 @@
/*
* #%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.audit;
import static java.util.Arrays.asList;
import static org.alfresco.rest.rm.community.base.TestData.*;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.ADD_TO_HOLD;
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.REMOVE_FROM_HOLD;
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.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.core.IsNot.not;
import static org.springframework.http.HttpStatus.CREATED;
import static org.testng.AssertJUnit.*;
import java.util.Collections;
import java.util.List;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
import org.alfresco.rest.rm.community.model.audit.AuditEvents;
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.rm.community.model.recordfolder.RecordFolder;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.service.RMAuditService;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class AuditHoldsTest extends BaseRMRestTest {
private final String PREFIX = generateTestPrefix(AuditAddToHoldTests.class);
private final String HOLD1 = PREFIX + "hold1";
private SiteModel publicSite;
private FileModel testFile;
@Autowired
private RMAuditService rmAuditService;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
private UserModel rmAdmin;
private RecordCategory recordCategory;
private RecordCategoryChild recordFolder1,recordFolder2;
private List<AuditEntry> auditEntries;
private String hold1NodeRef;
public static final String RECORD_FOLDER_THREE = "record-folder-three";
@BeforeClass(alwaysRun = true)
public void preconditionForAuditAddToHoldTests()
{
createRMSiteIfNotExists();
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
STEP("Create a hold");
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1, HOLD_REASON,
HOLD_DESCRIPTION);
STEP("Create a collaboration site with a test file.");
publicSite = dataSite.usingAdmin().createPublicRandomSite();
testFile = dataContent.usingAdmin().usingSite(publicSite).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
STEP("Create a record category with 2 folders and 1 record");
recordCategory = createRootCategory(getRandomName("recordCategory"));
recordFolder1 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder1");
recordFolder2 = createRecordFolder(recordCategory.getId(), PREFIX + "recFolder2");
Record recordToBeAdded = createElectronicRecord(recordFolder1.getId(), PREFIX + "record");
assertStatusCode(CREATED);
STEP("Add some items to the hold, then remove them from the hold");
final List<String> itemsList = asList(testFile.getNodeRefWithoutVersion(), recordToBeAdded.getId(), recordFolder2.getId());
final List<String> holdsList = Collections.singletonList(HOLD1);
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), recordToBeAdded.getId(), HOLD1);
holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(), itemsList, holdsList);
STEP("Delete the record folder that was held");
getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(recordFolder2.getId());
STEP("Rename the parent of the record that was held");
RecordFolder recordFolder = RecordFolder.builder().name(RECORD_FOLDER_THREE).build();
getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(recordFolder, recordFolder1.getId());
}
/**
* Data provider with hold events that have links to held items
*
* @return the hold events
*/
@DataProvider (name = "holdsEvents")
public Object[][] getHoldEvents()
{
return new AuditEvents[][]
{
{ ADD_TO_HOLD },
{ REMOVE_FROM_HOLD }
};
}
@Test (dataProvider = "holdsEvents")
public void checkItemPathLink(AuditEvents event) {
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), event);
assertFalse("Audit results should not be empty",auditEntries.size()==0);
final String auditedEvent = event + " - " + testFile.getName();
assertTrue("Audit results should contain one " + auditedEvent + " event",auditEntries.stream().anyMatch(e -> e.getEvent().startsWith(event.eventDisplayName)));
STEP("Check the audit log contains only an entry for add to hold.");
assertThat(auditEntries, is(not(empty())));
}
@AfterClass(alwaysRun = true)
private void cleanup() {
dataSite.usingAdmin().deleteSite(publicSite);
deleteRecordFolder(recordFolder1.getId());
deleteRecordFolder(recordFolder2.getId());
deleteRecordCategory(recordCategory.getId());
rmAuditService.clearAuditLog();
}
}

View File

@@ -0,0 +1,244 @@
/*
* #%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.audit;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
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.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
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.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class ElectronicRecordAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordsAPI recordApi;
/* electronic record details */
private static final String AUDIT_ELECTRONIC_RECORD = generateTestPrefix(ElectronicRecordAuditLogTest.class) + "electronic record";
private static final String AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD = "Complete Reopen Electronic Record";
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
private Record electronicRecord, electronicRecord2;
@BeforeClass(alwaysRun = true)
public void electronicRecordsAuditLogSetup()
{
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(),TITLE);
electronicRecord = createElectronicRecord(recordFolder1.getId(),AUDIT_ELECTRONIC_RECORD,rmAdmin.get());
}
@Test(description = "Audit log for newly filed electronic record")
@AlfrescoTest(jira="RM-4303")
public void newElectronicRecordAudit() {
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
// newly created record contains 2 events: "file to" and metadata update
// the order in which object creation and metadata update are listed isn't always identical due to
// both happening in the same transaction
assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "newElectronicRecordAudit",
description = "Viewing electronic record audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void electronicRecordAuditIsEvent()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "electronicRecordAuditIsEvent",
description = "Rename electronic record is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameElectronicRecord() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
Record renameElectronicRecord = createRecordModel("edited " + electronicRecord.getName(), "", "");
// rename record
getRestAPIFactory().getRecordsAPI().updateRecord(renameElectronicRecord, electronicRecord.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test (
dependsOnMethods = "newElectronicRecordAudit",
description = "Complete and reopen electronic record")
@AlfrescoTest(jira="RM-4303")
public void completeAndReopenElectronicRecord() {
electronicRecord2 = createElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_ELECTRONIC_RECORD);
// complete record
recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
electronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
// a record must be completed
assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
// Reopen record
recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
electronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(electronicRecord2.getId()).getAspectNames();
// a record mustn't be completed
assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
}
@Test
(
dependsOnMethods = "completeAndReopenElectronicRecord",
description = "File electronic record's audit log as record"
)
@AlfrescoTest(jira="RM-4303")
public void fileElectronicRecordAuditLogAsRecord()
{
// audit log is stored in the same folder, refresh it so that it appears in the list
HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
getRecordNodeRef(electronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
.replace("workspace://SpacesStore/",""));
// check audit log
AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
}
private String getFolderNodeRef(String folderId) {
return "workspace://SpacesStore/" + folderId;
}
private String getRecordNodeRef(String recordId) {
return "workspace/SpacesStore/" + recordId;
}
private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
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;
}
@AfterMethod
private void closeAuditLog() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass(alwaysRun = true)
private void electronicRecordAuditLogCleanup() {
deleteRecord(electronicRecord.getId());
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -0,0 +1,246 @@
/*
* #%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.audit;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
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.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
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.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class NonElectronicRecordAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordsAPI recordApi;
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
private Record nonElectronicRecord , nonElectronicRecord2;
private static final String AUDIT_NON_ELECTRONIC_RECORD = generateTestPrefix(NonElectronicRecordAuditLogTest.class) + "non electronic record";
private static final String AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD = "Complete Reopen Non-Electronic Record";
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
@BeforeClass(alwaysRun = true)
public void nonElectronicRecordAuditLogSetup()
{
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(),TITLE);
nonElectronicRecord = createNonElectronicRecord(recordFolder1.getId(),AUDIT_NON_ELECTRONIC_RECORD,rmAdmin.get());
}
@Test(description = "Audit log for newly filed non-electronic record")
@AlfrescoTest(jira="RM-4303")
public void newNonElectronicRecordAudit()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
// newly created record contains 3 events: "created object", "file to" and metadata update
assertTrue("File To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("File to")));
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
assertTrue("Created Object Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
}
@Test
(
dependsOnMethods = "newNonElectronicRecordAudit",
description = "Viewing Non electronic record audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void nonElectronicRecordAuditIsEvent()
{
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Audit View Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "nonElectronicRecordAuditIsEvent",
description = "Rename electronic record is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameNonElectronicRecord()
{
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
Record renameNonElectronicRecord = createRecordModel("edited " + nonElectronicRecord.getName(), "", "");
// rename record
getRestAPIFactory().getRecordsAPI().updateRecord(renameNonElectronicRecord, nonElectronicRecord.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Updated metadata Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test (dependsOnMethods = "newNonElectronicRecordAudit",description = "Complete and reopen electronic record")
@AlfrescoTest(jira="RM-4303")
public void completeAndReopenNonElectronicRecord()
{
nonElectronicRecord2 = createNonElectronicRecord(recordFolder1.getId(),AUDIT_COMPLETE_REOPEN_NON_ELECTRONIC_RECORD);
// complete record
recordApi.completeRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
nonElectronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
// a record must be completed
assertTrue("Record is not completed.",aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
List<AuditEntry> auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Complete Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Complete Record")));
// Reopen record
recordApi.reOpenRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
nonElectronicRecord2.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
List<String> aspects = recordsAPI.getRecord(nonElectronicRecord2.getId()).getAspectNames();
// a record mustn't be completed
assertFalse(aspects.contains(ASPECTS_COMPLETED_RECORD));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
auditEntries= auditLog.getRMAuditLogAll(getAdminUser().getUsername(),getAdminUser().getPassword(),100);
assertTrue("Reopen Record Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Reopen Record")));
}
@Test
(
dependsOnMethods = "completeAndReopenNonElectronicRecord",
description = "File electronic record's audit log as record"
)
@AlfrescoTest(jira="RM-4303")
public void fileNonElectronicRecordAuditLogAsRecord()
{
// audit log is stored in the same folder, refresh it so that it appears in the list
HttpResponse auditRecordHttpResponse = auditLog.logsAuditLogAsRecord(rmAdmin.get().getUsername(),rmAdmin.get().getPassword(),
getRecordNodeRef(nonElectronicRecord2.getId()),getFolderNodeRef(recordFolder1.getId()));
JSONObject auditRecordProperties = getAuditPropertyValues(auditRecordHttpResponse);
Record auditRecord = getRestAPIFactory().getRecordsAPI().getRecord(auditRecordProperties.get("record").toString()
.replace("workspace://SpacesStore/",""));
// check audit log
AssertJUnit.assertTrue(auditRecordProperties.get("recordName").toString().endsWith(".html"));
AssertJUnit.assertTrue(auditRecord.getAspectNames().stream().noneMatch(x -> x.startsWith(ASPECTS_COMPLETED_RECORD)));
}
private String getFolderNodeRef(String folderId) {
return "workspace://SpacesStore/" + folderId;
}
private String getRecordNodeRef(String recordId) {
return "workspace/SpacesStore/" + recordId;
}
private JSONObject getAuditPropertyValues(HttpResponse httpResponse) {
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;
}
@AfterMethod
private void closeAuditLog() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass(alwaysRun = true)
private void nonElectronicRecordAuditLogCleanup() {
deleteRecord(nonElectronicRecord.getId());
deleteRecord(nonElectronicRecord2.getId());
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -0,0 +1,120 @@
/*
* #%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.audit;
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.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
public class RecordCategoryAuditLogTest extends BaseRMRestTest {
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
private final String TEST_PREFIX = generateTestPrefix(RecordCategoryAuditLogTest.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private static final String AUDIT_CATEGORY = generateTestPrefix(RecordCategoryAuditLogTest.class) + "category";
private RecordCategory recordCategoryAudit;
@BeforeClass(alwaysRun = true)
public void recordCategoryAuditLogSetup() {
STEP("Create RM Site");
createRMSiteIfNotExists();
STEP("Create RM Admin user");
rmRolesAndActionsAPI.createUserAndAssignToRole(getAdminUser().getUsername(), getAdminUser().getPassword(), RM_ADMIN,
getAdminUser().getPassword(),
"Administrator");
}
@Test
@AlfrescoTest(jira = "RM-2768")
public void recordCategoryAudit() throws Exception {
STEP("Create root level category");
recordCategoryAudit = createRootCategory(AUDIT_CATEGORY);
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
// newly created record category contains 3 events: object creation, inherited permissions set to false and metadata update
// the order in which object creation and metadata update are listed isn't always identical due to
// both happening in the same transaction
assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "recordCategoryAudit",
description = "Viewing audit log is itself an auditable event"
)
@AlfrescoTest(jira="RM-4303")
public void recordCategoryAuditIsEvent() {
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "recordCategoryAuditIsEvent",
description = "Record category rename is an edit metadata event"
)
@AlfrescoTest(jira="RM-4303")
public void renameRecordCategory() {
String categoryName = "Category name " + getRandomAlphanumeric();
RecordCategory rootRecordCategory = createRootCategory(categoryName);
String newCategoryName = "Rename " + categoryName;
RecordCategory recordCategoryUpdated = RecordCategory.builder().name(newCategoryName).build();
RecordCategory renamedRecordCategory = getRestAPIFactory().getRecordCategoryAPI().updateRecordCategory(recordCategoryUpdated, rootRecordCategory.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@AfterClass(alwaysRun = true)
private void electronicRecordAuditLogCleanup() {
deleteRecordCategory(recordCategoryAudit.getId());
dataUser.deleteUser(new UserModel(RM_ADMIN,
getAdminUser().getPassword()));
auditLog.clearAuditLog(getAdminUser().getUsername(), getAdminUser().getPassword());
}
}

View File

@@ -0,0 +1,175 @@
/*
* #%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.audit;
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.rm.community.model.recordfolder.RecordFolder;
import org.alfresco.rest.v0.RMAuditAPI;
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
import org.alfresco.rest.v0.RecordFoldersAPI;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.Utility;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
import java.util.Optional;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_COMPLETED_RECORD;
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createRecordFolderModel;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.test.util.AssertionErrors.assertTrue;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;
public class RecordFolderAuditLogTest extends BaseRMRestTest {
private Optional<UserModel> rmAdmin;
@Autowired
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
@Autowired
private RMAuditAPI auditLog;
@Autowired
private RecordFoldersAPI recordFoldersAPI;
private RecordCategory category1;
private RecordCategoryChild recordFolder1;
public static final String TITLE = "Title";
public static final String DESCRIPTION = "Description";
@BeforeClass(alwaysRun = true)
public void recordFolderAuditLogSetup() {
createRMSiteIfNotExists();
rmAdmin = Optional.ofNullable(getDataUser().createRandomTestUser());
rmRolesAndActionsAPI.assignRoleToUser(
getDataUser().usingAdmin().getAdminUser().getUsername(),
getDataUser().usingAdmin().getAdminUser().getPassword(),
rmAdmin.get().getUsername(),
"Administrator");
}
@Test(description = "Audit log for empty record folder")
@AlfrescoTest(jira = "RM-4303")
public void recordFolderAudit() {
category1 = createRootCategory(TITLE, DESCRIPTION);
recordFolder1 = createFolder(category1.getId(), TITLE);
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Created Object Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Created Object")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test
(
dependsOnMethods = "recordFolderAudit",
description = "Viewing record folder audit log is itself an auditable event"
)
@AlfrescoTest(jira = "RM-4303")
public void recordFolderAuditIsEvent() {
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Audit View Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Audit View")));
}
@Test
(
dependsOnMethods = "recordFolderAuditIsEvent",
description = "Record folder rename is an edit metadata event"
)
@AlfrescoTest(jira = "RM-4303")
public void renameRecordFolder() {
auditLog.clearAuditLog(rmAdmin.get().getUsername(), rmAdmin.get().getPassword());
RecordFolder renameRecordFolder = createRecordFolderModel(category1.getId(), "edited");
getRestAPIFactory().getRecordFolderAPI().updateRecordFolder(renameRecordFolder, recordFolder1.getId());
assertStatusCode(OK);
// we expect 1 new event: "metadata update"
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
// assertTrue("Move To Event is not present.",auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Move to")));
assertTrue("Updated metadata Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Updated Metadata")));
}
@Test(dependsOnMethods = "recordFolderAudit",
description = "Close and reopen folder")
@AlfrescoTest(jira = "RM-4303")
public void closeReopenFolder() {
//close folder
recordFoldersAPI.closeRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
recordFolder1.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Folder Close Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Close Record Folder")));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
//reopen folder
recordFoldersAPI.reOpenRecordFolder(rmAdmin.get().getUsername(), rmAdmin.get().getPassword(),
recordFolder1.getName());
try
{
Utility.sleep(1000, 30000, () ->
{
List<AuditEntry> auditEntries = auditLog.getRMAuditLogAll(getAdminUser().getUsername(), getAdminUser().getPassword(), 100);
assertTrue("Reopen Record Event is not present.", auditEntries.stream().anyMatch(x -> x.getEvent().startsWith("Open Record Folder")));
});
}
catch (InterruptedException e)
{
fail("InterruptedException received while waiting for results.");
}
}
@AfterMethod
private void closeAuditLog()
{
auditLog.clearAuditLog(rmAdmin.get().getUsername(),rmAdmin.get().getPassword());
}
@AfterClass (alwaysRun = true)
public void recordFolderAuditLogCleanup()
{
deleteRecordFolder(recordFolder1.getId());
deleteRecordCategory(category1.getId());
dataUser.usingAdmin().deleteUser(new UserModel(rmAdmin.get().getUsername(), rmAdmin.get().getPassword()));
}
}

View File

@@ -0,0 +1,118 @@
/*
* #%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.rules;
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.rm.community.model.rules.ActionsOnRule;
import org.alfresco.rest.rm.community.model.rules.RuleDefinition;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI;
import org.alfresco.rest.rm.community.smoke.CreateCategoriesTests;
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.CoreUtil.createBodyForMoveCopy;
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
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 CopyToRuleOnFoldersTest extends BaseRMRestTest {
private RecordCategory category;
private RecordCategoryChild folder1,folder2;
private final static String title = "Run in background";
private final String TEST_PREFIX = generateTestPrefix(CopyToRuleOnFoldersTest.class);
private final String RM_ADMIN = TEST_PREFIX + "rm_admin";
private final String electronicRecord = TEST_PREFIX + "record_electronic_for_copyTo";
private final String nonElectronicRecord = TEST_PREFIX + "record_non_electronic_for_copyTo";
@Autowired
private RulesAPI rulesAPI;
@Test
@AlfrescoTest(jira = "RM-2994")
public void copyToRuleOnFoldersTest()
{
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
.runInBackground(true).title(title)
.actions(Collections.singletonList(ActionsOnRule.COPY_TO.getActionValue()));
STEP("Create the RM site if doesn't exist");
createRMSiteIfNotExists();
STEP("Create record categories and record folders");
category= createRootCategory(getRandomName("recordCategory"));
String folder1 = createCategoryFolderInFilePlan().getId();
String folder2 = createCategoryFolderInFilePlan().getId();
// create a rule on folder
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX + folder1, ruleDefinition);
// create electronic record in record folder
String electronicRecordId = createElectronicRecord(folder1, ELECTRONIC_RECORD_NAME).getId();
assertStatusCode(CREATED);
// create non-electronic record in record folder
String nonElectronicRecord = createElectronicRecord(folder1, NONELECTRONIC_RECORD_NAME).getId();
assertStatusCode(CREATED);
// Move the electronic and non-electronic records from "Category with records"> "Folder with rule"
// to "Copy Category with records" > "Folder with rule"
getRestAPIFactory().getNodeAPI(toContentModel(folder1)).copy(createBodyForMoveCopy(category.getId()));
getRestAPIFactory().getNodeAPI(toContentModel( electronicRecord)).move(createBodyForMoveCopy(folder2));
getRestAPIFactory().getNodeAPI(toContentModel( nonElectronicRecord)).move(createBodyForMoveCopy(folder2));
RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
// Delete the record category
RecordCategoryAPI recordCategoryAPI = getRestAPIFactory().getRecordCategoryAPI();
String recordCategoryId = category.getId();
recordCategoryAPI.deleteRecordCategory(recordCategoryId);
recordsAPI.deleteRecord(electronicRecord);
recordsAPI.deleteRecord(nonElectronicRecord);
assertStatusCode(NO_CONTENT);
}
}

View File

@@ -0,0 +1,229 @@
/*
* #%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.rules;
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.model.user.UserRoles;
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
import org.alfresco.rest.rm.community.smoke.FileAsRecordTests;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.test.AlfrescoTest;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
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 org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
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.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.CREATED;
@AlfrescoTest (jira = "APPS-36")
public class FileAsRecordRuleTests extends BaseRMRestTest
{
private UserModel nonRMUser, rmManager;
private RecordCategory category_manager, category_admin;
private RecordCategoryChild folder_admin, folder_manager ;
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 FolderModel testFolder;
private FileModel document,inPlaceRecord;
@Autowired
private RoleService roleService;
@Autowired
private RulesAPI rulesAPI;
/**
* Create preconditions:
* 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
* 5. A collaboration folder with rule set to declare and file as record to a record folder
**/
@BeforeClass(alwaysRun = true)
public void preconditionForDeclareFileAsRecordRuleTests()
{
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 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);
STEP("Create a collaboration folder with a rule set to declare and file as record to a record folder");
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);
assertStatusCode(CREATED);
}
/**
* Given I am a user that can create a rule on a folder in a collaboration site
* When I am creating the rule
* Then I have the option of adding a "Declare and File as Record" action to the rule
* <p>
* Given I am creating a rule
* When I add the "Declare and File as Record" action to the rule
* Then I am able to select the record folder I want the declared record to be filed to
* <p>
* Given I am configuring a "Declare and File as Record" action within a rule
* And I have at least one records management role (eg RM User)
* When I am selecting the record folder location to file the declared record to
* Then I see the record folders in the file plan that I have file access to as the creator of the record
**/
@Test
public void declareAsRecordRuleAsRMUserWithFilingPermissions() {
STEP("Create a collaboration folder");
testFolder = dataContent.usingSite(testSite)
.usingUser(rmManager)
.createFolder();
STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
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);
assertStatusCode(CREATED);
}
/**
* Given I am configuring a "Declare and File as Record" action within a rule
* And I don't have a records management role
* When I am selecting the record folder location to file the declared record to
* Then I can see only the file plan
*/
@Test
public void declareAsRecordRuleAsNonRMUser()
{
STEP("Create a collaboration folder");
testFolder = dataContent.usingSite(testSite)
.usingUser(nonRMUser)
.createFolder();
STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
.applyToChildren(true)
.actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
rulesAPI.createRule(nonRMUser.getUsername(), nonRMUser.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
assertStatusCode(CREATED);
}
/**
* Given I have not selected a record folder location
* When the rule is triggered
* Then the file is declared as record to the UnFiled Records folder
*/
@Test
public void triggerDeclareToUnfiledRuleAsNonRMUser()
{
STEP("Create a collaboration folder with a rule set to declare and file as record without a record folder location");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
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);
assertStatusCode(CREATED);
STEP("Create as nonRMUser a new file into the previous folder in order to trigger the rule");
inPlaceRecord = dataContent.usingUser(nonRMUser).usingResource(testFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
// Verify that 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(inPlaceRecord.getNodeRefWithoutVersion()))
.collect(Collectors.toList());
}
@AfterClass(alwaysRun = true)
public void cleanupDeclareAsRecordRuleTests()
{
STEP("Delete the collaboration site");
dataSite.usingUser(nonRMUser).deleteSite(testSite);
STEP("Delete Users");
dataUser.deleteUser(nonRMUser);
dataUser.deleteUser(rmManager);
STEP("Delete categories");
getRestAPIFactory().getFilePlansAPI().getRootRecordCategories(FILE_PLAN_ALIAS).getEntries().forEach(recordCategoryEntry ->
deleteRecordCategory(recordCategoryEntry.getEntry().getId()));
}
}

View File

@@ -0,0 +1,221 @@
/*
* #%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.rules;
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.model.user.UserRoles;
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
import org.alfresco.rest.rm.community.smoke.FileAsRecordTests;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FileType;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
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 org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
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.utility.data.RandomData.getRandomName;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.CREATED;
public class FileVersionAsRecordRuleTest extends BaseRMRestTest {
private UserModel nonRMuser, rmManager;
private RecordCategory category_manager, category_admin;
private RecordCategoryChild folder_admin, folder_manager ;
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 FolderModel testFolder;
private FileModel document,inPlaceRecord;
@Autowired
private RoleService roleService;
@Autowired
private RulesAPI rulesAPI;
@BeforeClass(alwaysRun = true)
public void createTestPrecondition()
{
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);
STEP("Create a collaboration folder with a rule set to declare and file version as record to a record folder");
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);
assertStatusCode(CREATED);
}
@Test
public void declareVersionAsRecordRuleAsRMUserWithFilingPermissions()
{
STEP("Create a collaboration folder");
testFolder = dataContent.usingSite(testSite)
.usingUser(rmManager)
.createFolder();
STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
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(rmManager.getUsername(), rmManager.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
assertStatusCode(CREATED);
}
@Test
public void declareVersionAsRecordRuleAsNonRMUser()
{
STEP("Create a collaboration folder");
testFolder = dataContent.usingSite(testSite)
.usingUser(nonRMuser)
.createFolder();
STEP("Create a rule with Declare as Record action and check that user can select a record folder.");
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
.applyToChildren(true)
.actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
rulesAPI.createRule(nonRMuser.getUsername(), nonRMuser.getPassword(), NODE_PREFIX + testFolder.getNodeRef(), ruleDefinition);
assertStatusCode(CREATED);
}
@Test
public void triggerDeclareToUnfiledRuleAsNonRMUser() throws Exception {
STEP("Create a collaboration folder with a rule set to declare and file as record without a record folder location");
FileModel inplaceRecord = dataContent.usingSite(testSite).usingUser(nonRMuser)
.createContent(new FileModel("declareAndFileToIntoUnfiledRecordFolder",
FileType.TEXT_PLAIN));
RecordCategory recordCategory = new RecordCategory().builder()
.id(category_manager.getId()).build();
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description")
.applyToChildren(true)
.actions(Collections.singletonList(ActionsOnRule.DECLARE_AS_RECORD.getActionValue()));
rulesAPI.createRule(nonRMuser.getUsername(), nonRMuser.getPassword(), NODE_PREFIX + inplaceRecord.getNodeRef(), ruleDefinition);
assertStatusCode(CREATED);
STEP("Create as nonRMuser a new file into the previous folder in order to trigger the rule");
inPlaceRecord = dataContent.usingUser(nonRMuser).usingResource(testFolder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
// 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(inplaceRecord.getNodeRefWithoutVersion()))
.collect(Collectors.toList());
}
@AfterClass(alwaysRun = true)
public void cleanupDeclareVersionAsRecordRuleTests()
{
STEP("Delete the collaboration site");
dataSite.usingUser(nonRMuser).deleteSite(testSite);
STEP("Delete Users");
dataUser.deleteUser(nonRMuser);
dataUser.deleteUser(rmManager);
STEP("Delete categories");
getRestAPIFactory().getFilePlansAPI().getRootRecordCategories(FILE_PLAN_ALIAS).getEntries().forEach(recordCategoryEntry ->
deleteRecordCategory(recordCategoryEntry.getEntry().getId()));
}
}

View File

@@ -0,0 +1,237 @@
/*
* #%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.rules;
import org.alfresco.rest.model.RestNodeModel;
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
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.rm.community.model.rules.ActionsOnRule;
import org.alfresco.rest.rm.community.model.rules.ConditionsOnRule;
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.UnfiledContainerChildEntry;
import org.alfresco.rest.rm.community.model.user.UserRoles;
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
import org.alfresco.rest.search.RestRequestQueryModel;
import org.alfresco.rest.v0.HoldsAPI;
import org.alfresco.rest.v0.RecordsAPI;
import org.alfresco.rest.v0.RulesAPI;
import org.alfresco.rest.v0.service.RoleService;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import static java.lang.Integer.MAX_VALUE;
import static java.util.Arrays.asList;
import static org.alfresco.rest.core.v0.BaseAPI.NODE_PREFIX;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_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.rest.rm.community.utils.FilePlanComponentsUtil.*;
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.*;
import static org.testng.Assert.assertNotNull;
public class MoveToRuleOnFoldersTest extends BaseRMRestTest{
private RecordCategoryChild recordFolder2;
private RecordCategoryChild recordFolder1;
private String nonElectronicId;
public Record electronicRecord;
private String ruleType = ConditionsOnRule.UPDATE.getWhenConditionValue();
private UserModel rmAdmin;
public RecordCategory RecordCategoryOne;
private RecordCategoryChild recordFolder;
public static final String RECORD_FOLDER_ONE = "record-folder-one";
private final String TEST_PREFIX = generateTestPrefix(MoveToRuleOnFoldersTest.class);
private final String RECORD_CATEGORY_ONE = TEST_PREFIX + "category";
private final String recordName = "Test record";
private final String recordTitle = recordName + " title";
private final String recordDescription = recordName + " description";
private Record nonElectrinicRecordModel;
private RecordFolderAPI recordFolderAPI;
public String title,description,box,file,shelf,storageLocation,name;
@Autowired
private RulesAPI rulesAPI;
@Autowired
private HoldsAPI holdsAPI;
@Autowired
private RoleService roleService;
@Autowired
public RecordsAPI recordsAPI;
@BeforeClass(alwaysRun = true)
public void precondition()
{
//create RM site
createRMSiteIfNotExists();
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
//create root category, create folders , add electronic and non electronic records
RecordCategoryOne = createRootCategory(RECORD_CATEGORY_ONE);
recordFolder1=createRecordFolder(RecordCategoryOne.getId(), getRandomName("recFolder"));
// recordFolder1_id = createRecordFolder(RecordCategoryOne.getId(), getRandomName("recFolder")).getId();
recordFolder2 = createFolder(getAdminUser(),RecordCategoryOne.getId(),getRandomName("recFolder"));
STEP("CREATE ELECTRONIC RECORD");
recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder1.getId(), getFile(IMAGE_FILE));
STEP("Check the electronic record has been created");
assertStatusCode(CREATED);
STEP("Create a non-electronic record by completing some of the fields");
// Use these properties for non-electronic record to be created
title = "Title " + getRandomAlphanumeric();
description = "Description " + getRandomAlphanumeric();
box = "Box "+ getRandomAlphanumeric();
file = "File " + getRandomAlphanumeric();
shelf = "Shelf " + getRandomAlphanumeric();
storageLocation = "Storage Location " + getRandomAlphanumeric();
name = "Record " + getRandomAlphanumeric();
Random random = new Random();
Integer numberOfCopies = random.nextInt(MAX_VALUE);
Integer physicalSize = random.nextInt(MAX_VALUE);
// Set values of all available properties for the non electronic records
nonElectrinicRecordModel = createFullNonElectronicRecordModel(name, title, description, box, file, shelf, storageLocation, numberOfCopies, physicalSize);
// Create non-electronic record
nonElectronicId = recordFolderAPI.createRecord(nonElectrinicRecordModel, recordFolder1.getId()).getId();
STEP("Check the non-electronic record has been created");
assertStatusCode(CREATED);
}
@Test
public void MoveToRuleFoldersTest()
{
String CatName=RecordCategoryOne.getName();
String folder2name=recordFolder2.getName();
String recfolder2_path="/"+CatName+"/"+folder2name;
STEP("create a rule MOVE_TO for folder 1");
RuleDefinition ruleDefinition = RuleDefinition.createNewRule().title("name").description("description1")
.runInBackground(true).title(title)
.actions(Collections.singletonList(ActionsOnRule.MOVE_TO.getActionValue())).ruleType(ruleType).path(recfolder2_path);
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX +recordFolder1.getId() , ruleDefinition);
STEP("Update metadata for Non-Electronic Record");
updateRecordMetadata();
STEP("Delete ELECTRONIC AND NON-ELECTRONIC RECORDS IN FOLDER 2");
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
recordsAPI.deleteRecord(electronicRecord.getId());
assertStatusCode(NO_CONTENT);
recordsAPI.deleteRecord(nonElectronicId);
assertStatusCode(NO_CONTENT);
STEP("RULE CREATION FOR FOLDER 1 WITHOUT RUNNING IN BACKGROUND");
RuleDefinition ruleDefinition_notinbackground = RuleDefinition.createNewRule().title("name").description("description1")
.runInBackground(false).title(title)
.actions(Collections.singletonList(ActionsOnRule.MOVE_TO.getActionValue())).ruleType(ruleType).path(recfolder2_path);
rulesAPI.createRule(getAdminUser().getUsername(), getAdminUser().getPassword(), NODE_PREFIX +recordFolder1.getId() , ruleDefinition);
STEP("CREATE ELECTRONIC AND NON-ELECTRONIC RECORDS");
electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder1.getId(), getFile(IMAGE_FILE));
STEP("Check the electronic record has been created");
assertStatusCode(CREATED);
nonElectronicId = recordFolderAPI.createRecord(nonElectrinicRecordModel, recordFolder1.getId()).getId();
STEP("Check the non-electronic record has been created");
assertStatusCode(CREATED);
STEP("UPDATE METADATA");
updateRecordMetadata();
STEP("CHECK IF ELECTRONIC AND NON-ELECTRONIC RECORDS MOVED TO FOLDER2");
updateRecordMetadata();
}
@AfterClass(alwaysRun = true)
public void cleanMoveToRuleOnFoldersTest()
{
deleteRecordCategory(RecordCategoryOne.getId());
getDataUser().deleteUser(rmAdmin);
}
private String getModifiedPropertyValue(String originalValue) {
/* to be used to append to modifications */
String MODIFIED_PREFIX = "modified_";
return MODIFIED_PREFIX + originalValue;
}
private void updateRecordMetadata(){
STEP("Update metadata for Non-Electronic Record");
org.alfresco.rest.rm.community.requests.gscore.api.RecordsAPI recordsAPI = getRestAPIFactory().getRecordsAPI();
Record nonelecrecord = recordsAPI.getRecord(nonElectronicId);
String nonelecnewName = getModifiedPropertyValue(nonElectrinicRecordModel.getName());
String nonelecnewTitle = getModifiedPropertyValue(nonElectrinicRecordModel.getProperties().getTitle());
String nonelecnewDescription = getModifiedPropertyValue(nonElectrinicRecordModel.getProperties().getDescription());
recordsAPI.updateRecord(createRecordModel(nonelecnewName, nonelecnewDescription, nonelecnewTitle),nonelecrecord.getId());
assertStatusCode(OK);
STEP("Update metadata for Electronic Record");
Record elecrecord = recordsAPI.getRecord(electronicRecord.getId());
String elecnewName = getModifiedPropertyValue(electronicRecord.getName());
String elecnewTitle = getModifiedPropertyValue(electronicRecord.getProperties().getTitle());
String elecnewDescription = getModifiedPropertyValue(electronicRecord.getProperties().getDescription());
recordsAPI.updateRecord(createRecordModel(elecnewName, elecnewDescription, elecnewTitle),elecrecord.getId());
assertStatusCode(OK);
}
}

View File

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

View File

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

View File

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

View File

@@ -30,8 +30,10 @@ package org.alfresco.module.org_alfresco_module_rm.job;
import static org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExecuterAbstractBase.PARAM_NO_ERROR_CHECK;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -47,7 +49,6 @@ import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.springframework.extensions.surf.util.I18NUtil;
/**
@@ -64,7 +65,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
/** batching properties */
private int batchSize;
public static final int DEFAULT_BATCH_SIZE = 500;
private static final String MSG_NODE_FROZEN = "rm.action.node.frozen.error-message";
/** list of disposition actions to automatically execute */
private List<String> dispositionActions;
@@ -194,6 +194,7 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
boolean hasMore = true;
int skipCount = 0;
List<NodeRef> resultNodes = new ArrayList<>();
if (batchSize < 1)
{
@@ -214,7 +215,14 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
// execute search
ResultSet results = searchService.query(params);
List<NodeRef> resultNodes = results.getNodeRefs();
if(results != null)
{
// filtering out the hold/freezed cases from the result set
resultNodes =
results.getNodeRefs().stream().filter(node -> nodeService.getPrimaryParent(node) == null ?
!freezeService.isFrozenOrHasFrozenChildren(node) :
!freezeService.isFrozenOrHasFrozenChildren(nodeService.getPrimaryParent(node).getParentRef())).collect(Collectors.toList());
}
hasMore = results.hasMore();
skipCount += resultNodes.size(); // increase by page size
results.close();
@@ -265,12 +273,6 @@ public class DispositionLifecycleJobExecuter extends RecordsManagementJobExecute
}
Map<String, Serializable> props = Map.of(PARAM_NO_ERROR_CHECK, false);
if (freezeService.isFrozenOrHasFrozenChildren(parent.getParentRef()))
{
log.debug(I18NUtil.getMessage(MSG_NODE_FROZEN, dispAction));
continue;
}
try
{
// execute disposition action

View File

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

View File

@@ -170,7 +170,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
executer.executeImpl();
// then
verify(mockedNodeService, times(2)).getPrimaryParent(any(NodeRef.class));
// ensure the query is executed and closed
verifyQueryTimes(2);
@@ -206,7 +206,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
executer.executeImpl();
// then
verify(mockedNodeService, times(1)).getPrimaryParent(any(NodeRef.class));
// ensure the query is executed and closed
verifyQueryTimes(1);
@@ -262,11 +262,11 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
// ensure each node is process correctly
// node1
verify(mockedNodeService, times(1)).getProperty(node1, RecordsManagementModel.PROP_DISPOSITION_ACTION);
verify(mockedNodeService, times(1)).getPrimaryParent(node1);
verify(mockedNodeService, times(3)).getPrimaryParent(node1);
verify(mockedRecordsManagementActionService, times(1)).executeRecordsManagementAction(eq(parent), eq(CUTOFF), anyMap());
// node2
verify(mockedNodeService, times(1)).getProperty(node2, RecordsManagementModel.PROP_DISPOSITION_ACTION);
verify(mockedNodeService, times(1)).getPrimaryParent(node2);
verify(mockedNodeService, times(3)).getPrimaryParent(node2);
verify(mockedRecordsManagementActionService, times(1)).executeRecordsManagementAction(eq(parent), eq(RETAIN), anyMap());
// ensure no more interactions
@@ -329,7 +329,7 @@ public class DispositionLifecycleJobExecuterUnitTest extends BaseUnitTest
// call the service
executer.executeImpl();
// check the loop iterated trough all the elements
// check the loop iterated through all the elements
verify(mockedNodeService).exists(node1);
verify(mockedNodeService).exists(node2);
verify(mockedNodeService).exists(node3);

View File

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

View File

@@ -38,6 +38,9 @@ tags:
description: Retrieve and manage unfiled records containers
- name: unfiled-record-folders
description: Retrieve and manage unfiled record folders
- name: events
description: Retrieve and manage retention events
paths:
## GS sites
'/gs-sites':
@@ -2091,7 +2094,172 @@ paths:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
'/events':
get:
tags:
- events
summary: List all available retention events
description: |
Gets the list of events that can be used by retention steps
operationId: getAllEvents
produces:
- application/json
parameters:
- $ref: '#/parameters/skipCountParam'
- $ref: '#/parameters/maxItemsParam'
responses:
'200':
description: Successful response
schema:
$ref: '#/definitions/EventPaging'
'400':
description: |
Invalid parameter: value of **maxItems** or **skipCount** is invalid
'401':
description: Authentication failed
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
post:
tags:
- events
summary: Create a new retention event
description: |
Creates a new event that can be used by retention schedules.
operationId: createEvent
parameters:
- in: body
name: eventBodyCreate
description: The new event.
required: true
schema:
$ref: '#/definitions/EventBody'
consumes:
- application/json
produces:
- application/json
responses:
'201':
description: Successful response
schema:
$ref: '#/definitions/EventEntry'
'400':
description: |
Invalid parameter: **name** or **type** is invalid
'401':
description: Authentication failed
'403':
description: Current user does not have permission to create event
'409':
description: Cannot create event. An event with the name **name** already exists
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
'/events/{eventId}':
get:
tags:
- events
summary: Return event for given eventId
description: |
Gets information about the retention event with id **eventId**.
operationId: getEvent
produces:
- application/json
parameters:
- $ref: '#/parameters/eventIdParam'
responses:
'200':
description: Successful response
schema:
$ref: '#/definitions/EventEntry'
'400':
description: |
Invalid parameter: **eventId** is invalid
'401':
description: Authentication failed
'404':
description: "**eventId** does not exist"
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
put:
tags:
- events
summary: Update event for given eventId
operationId: updateEvent
description: |
Updates retention event with id **eventId**.
produces:
- application/json
parameters:
- $ref: '#/parameters/eventIdParam'
- in: body
name: eventBodyUpdate
description: The event information to update.
required: true
schema:
$ref: '#/definitions/EventBody'
responses:
'200':
description: Successful response
schema:
$ref: '#/definitions/EventEntry'
'400':
description: |
Invalid parameter: The update request is invalid or **eventId** is not a valid format or **eventBodyUpdate** is invalid
'401':
description: Authentication failed
'403':
description: Current user does not have permission to update events
'404':
description: "**eventId** does not exist"
'409':
description: Cannot update event. An event with the name **name** already exists
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
'/event-types':
get:
tags:
- events
summary: List all the retention event types
description: |
Gets a list of all the retention event types.
operationId: getAllEventTypes
produces:
- application/json
parameters:
- $ref: '#/parameters/skipCountParam'
- $ref: '#/parameters/maxItemsParam'
responses:
'200':
description: Successful response
schema:
$ref: '#/definitions/EventTypePaging'
'400':
description: |
Invalid parameter: value of **maxItems** or **skipCount** is invalid
'401':
description: Authentication failed
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
parameters:
## event
eventIdParam:
name: eventId
in: path
description: The identifier of an event.
required: true
type: string
## File plans
filePlanEntryIncludeParam:
name: include
@@ -3760,3 +3928,91 @@ definitions:
- SiteCollaborator
- SiteContributor
- SiteManager
EventPaging:
type: object
properties:
list:
type: object
properties:
pagination:
$ref: '#/definitions/Pagination'
entries:
type: array
items:
$ref: '#/definitions/EventEntry'
EventEntry:
type: object
required:
- entry
properties:
entry:
$ref: '#/definitions/Event'
Event:
type: object
required:
- id
- name
- type
properties:
id:
type: string
description: this is the id of the event
name:
type: string
description: This is the unique display label of the event
type:
type: string
description: this is event type
EventBody:
type: object
required:
- name
properties:
name:
type: string
description: This is the unique display label of the event
type:
type: string
description: this is event type
default: Simple
EventTypePaging:
type: object
properties:
list:
type: object
properties:
pagination:
$ref: '#/definitions/Pagination'
entries:
type: array
items:
$ref: '#/definitions/EventTypeEntry'
EventTypeEntry:
type: object
required:
- entry
properties:
entry:
$ref: '#/definitions/EventType'
EventType:
type: object
required:
- id
- name
properties:
id:
type: string
description: this is the event type id
name:
type: string
description: this is event type name
isAutomatic:
type: boolean
description: Whether events of this type need completing manually or can be completed automatically
default: true
associationName:
type: string
description: The association used to determine whether automatic events of this type are complete
actionOnAssociatedNode:
type: string
description: If an association name is set for this event type then it is possible to require an action to be completed on the associated node

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-community-repo</artifactId>
<version>17.147</version>
<version>20.28-SNAPSHOT</version>
</parent>
<properties>
@@ -134,7 +134,7 @@
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>6.3.1</version>
<version>6.4.0</version>
</dependency>
<!-- the cxf libs were updated, see dependencyManagement section -->

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,21 @@
#!/usr/bin/env bash
set -x
export DOCKER_COMPOSE_PATH=$1
export CLEAN_UP="$2"
export DOCKER_COMPOSES=""
export CLEAN_UP=""
if [ -z "$DOCKER_COMPOSE_PATH" ]
for var in "$@"
do
if [ "$var" == "no-clean-up" ]
then
export CLEAN_UP="$var"
else
export DOCKER_COMPOSES+="--file $var "
fi
done
if [ -z "$DOCKER_COMPOSES" ]
then
echo "Please provide path to docker-compose.yml: \"${0##*/} /path/to/docker-compose.yml\""
exit 1
@@ -15,8 +27,8 @@ fi
# The second parameter can be used to avoid doing a clean up if we are doing a restart test.
if [ "$CLEAN_UP" != "no-clean-up" ]
then
docker-compose --file "${DOCKER_COMPOSE_PATH}" kill
docker-compose --file "${DOCKER_COMPOSE_PATH}" rm -f
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") kill
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") rm -f
export GENERATED_IMAGES=$(docker images | grep '^environment_' | awk '{ print $3 }')
if [ -n "$GENERATED_IMAGES" ]
@@ -31,7 +43,7 @@ export TRANSFORMERS_TAG=$(mvn help:evaluate -Dexpression=dependency.alfresco-tra
export TRANSFORM_ROUTER_TAG=$(mvn help:evaluate -Dexpression=dependency.alfresco-transform-service.version -q -DforceStdout)
# .env files are picked up from project directory correctly on docker-compose 1.23.0+
docker-compose --file "${DOCKER_COMPOSE_PATH}" --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") up -d
docker-compose ${DOCKER_COMPOSES} --project-directory $(dirname "${DOCKER_COMPOSE_PATH}") up -d
if [ $? -eq 0 ]
then

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,103 @@
package org.alfresco.rest.actions.email;
import static java.util.Objects.requireNonNull;
import static org.hamcrest.Matchers.notNullValue;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.json.JsonObject;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.core.JsonBodyGenerator;
import org.alfresco.utility.model.FileModel;
import org.alfresco.utility.model.FileType;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.UserModel;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class EmailTemplateTest extends RestTest {
public static final String MAIL_ACTION = "mail";
private UserModel adminUser;
private UserModel testUser;
private FolderModel testFolder;
@BeforeClass(alwaysRun = true)
public void dataPreparation() throws Exception {
adminUser = dataUser.getAdminUser();
testUser = dataUser.createRandomTestUser();
testSite = dataSite.usingUser(testUser)
.createPublicRandomSite();
testFolder = dataContent.usingUser(testUser)
.usingSite(testSite)
.createFolder();
}
@Test
public void adminCanSendEmailUsingTemplateWithModelAsString() throws Exception
{
String templateId = uploadEmailTemplate("simpleEmailTemplate.ftl");
// Create the model for use with email template
JsonObject args = JsonBodyGenerator.defineJSON()
.add("args", JsonBodyGenerator.defineJSON()
.add("name", "testname")
.build())
.build();
String emailModel = args.toString();
// Send an email using the template
restClient.authenticateUser(adminUser)
.withCoreAPI()
.usingActions()
.executeAction(MAIL_ACTION, testFolder, createMailWithTemplateParameters(adminUser, testUser, templateId, emailModel));
restClient.onResponse()
.assertThat().statusCode(HttpStatus.ACCEPTED.value())
.assertThat().body("entry.id", notNullValue());
}
private String uploadEmailTemplate(String templateName) throws IOException
{
final String templateContent = getTemplateContent(templateName);
final FileModel templateToCreate = new FileModel(templateName, FileType.TEXT_PLAIN, templateContent);
final FileModel createdTemplate = dataContent.usingAdmin()
.usingResource(testFolder)
.createContent(templateToCreate);
return createdTemplate.getNodeRef();
}
private String getTemplateContent(String templateName) throws IOException
{
final String templateClasspathLocation = "/shared-resources/testdata/" + templateName;
try (InputStream templateStream = getClass().getResourceAsStream(templateClasspathLocation))
{
requireNonNull(templateStream, "Couldn't locate `" + templateClasspathLocation + "`");
return new String(templateStream.readAllBytes());
}
}
private static Map<String, Serializable> createMailWithTemplateParameters(UserModel sender, UserModel recipient, String templateId, Serializable model)
{
Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put("from", sender.getEmailAddress());
parameterValues.put("to", recipient.getEmailAddress());
parameterValues.put("subject", "Test");
parameterValues.put("template", "workspace://SpacesStore/" + templateId);
parameterValues.put("template_model", model);
return parameterValues;
}
}

View File

@@ -14,6 +14,7 @@ import org.alfresco.utility.testrail.annotation.TestRail;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
public class AddFavoritesTests extends RestTest
@@ -354,6 +355,7 @@ public class AddFavoritesTests extends RestTest
@TestRail(section = { TestGroup.REST_API, TestGroup.FAVORITES }, executionType = ExecutionType.REGRESSION,
description = "Verify add file favorite with tag id returns status code 404")
@Test(groups = { TestGroup.REST_API, TestGroup.FAVORITES, TestGroup.REGRESSION })
@Ignore
public void addFileFavoriteUsingTagId() throws Exception
{
FileModel file = dataContent.usingSite(siteModel).usingUser(adminUserModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModelWithModifiedValues;
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.testng.Assert.assertEquals;
@@ -39,10 +39,12 @@ 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.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.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -72,26 +74,96 @@ public class GetInheritedRulesTests extends RestTest
STEP("Create a parent and child folder, each with inheriting rules");
FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
RestRuleModel parentRule = createRuleModelWithModifiedValues();
parentRule = restClient.authenticateUser(user).withCoreAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
RestRuleModel childRule = createRuleModelWithModifiedValues();
childRule = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
parentRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
RestRuleSettingsModel enabled = new RestRuleSettingsModel();
enabled.setValue(true);
restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
restClient.assertStatusCodeIs(HttpStatus.OK);
RestRuleModel childRule = rulesUtils.createRuleModelWithDefaultValues();
childRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().createSingleRule(childRule);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
STEP("Get the rules in the default rule set for the child folder");
RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
RestRuleModelsCollection rules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingDefaultRuleSet().getListOfRules();
restClient.assertStatusCodeIs(HttpStatus.OK);
rules.assertThat().entriesListContains("id", childRule.getId())
.and().entriesListCountIs(1);
STEP("Get the rules in the inherited rule set for the child folder");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
restClient.assertStatusCodeIs(HttpStatus.OK);
String inheritedRuleSetId = ruleSets.getEntries().stream()
.filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
.findFirst().get().onModel().getId();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withCoreAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
restClient.assertStatusCodeIs(HttpStatus.OK);
inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
.and().entriesListCountIs(1);
}
/**
* Check we get no (inherited) rules when inheritance is disabled in the child folder.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void getInheritedRules_childFolderInheritanceDisabled()
{
STEP("Create a parent and child folder, with inheritable parent rule");
FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(parentRule);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
STEP("Disable inheritance in the child folder");
RestRuleSettingsModel enabledInheritance = new RestRuleSettingsModel();
enabledInheritance.setValue(false);
restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabledInheritance);
restClient.assertStatusCodeIs(HttpStatus.OK);
STEP("The child folder should have no rule sets");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).getListOfRuleSets();
restClient.assertStatusCodeIs(HttpStatus.OK);
ruleSets.assertThat().entriesListIsEmpty();
}
/**
* Check that non-inheritable rules owned by the parent folder are not found inside the child folder.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
public void inheritance_test()
{
STEP("Create a parent and child folder, with an inheritable and a non-inheritable parent rule");
FolderModel parent = dataContent.usingUser(user).usingSite(site).createFolder();
FolderModel child = dataContent.usingUser(user).usingResource(parent).createFolder();
RestRuleModel inheritableRule = rulesUtils.createInheritableRuleModel();
inheritableRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(inheritableRule);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
RestRuleModel nonInheritableRule = rulesUtils.createRuleModelWithDefaultValues();
nonInheritableRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parent).usingDefaultRuleSet().createSingleRule(nonInheritableRule);
restClient.assertStatusCodeIs(HttpStatus.CREATED);
STEP("The inherited rule set for the child folder should only return the inheritable rule");
RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).include("inclusionType").getListOfRuleSets();
restClient.assertStatusCodeIs(HttpStatus.OK);
String inheritedRuleSetId = ruleSets.getEntries().stream()
.filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
.findFirst().get().onModel().getId();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(child).usingRuleSet(inheritedRuleSetId).getListOfRules();
restClient.assertStatusCodeIs(HttpStatus.OK);
inheritedRules.assertThat().entriesListContains("id", inheritableRule.getId())
.and().entriesListDoesNotContain("id",nonInheritableRule.getId())
.and().entriesListCountIs(1);
}
/**
* Check that we only get each rule once with linking and inheritance, and the order is correct.
* <p>
@@ -111,23 +183,28 @@ public class GetInheritedRulesTests extends RestTest
FolderModel folderB = dataContent.usingUser(user).usingResource(folderA).createFolder();
FolderModel folderC = dataContent.usingUser(user).usingResource(folderB).createFolder();
FolderModel folderD = dataContent.usingUser(user).usingResource(folderC).createFolder();
RestRuleModel ruleB = restClient.authenticateUser(user).withCoreAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleC = restClient.authenticateUser(user).withCoreAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleD = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(createRuleModelWithModifiedValues());
RestRuleModel ruleB = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderB).usingDefaultRuleSet().createSingleRule(rulesUtils.createInheritableRuleModel());
RestRuleModel ruleC = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingDefaultRuleSet().createSingleRule(rulesUtils.createInheritableRuleModel());
RestRuleModel ruleD = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).usingDefaultRuleSet().createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
RestRuleSettingsModel enabled = new RestRuleSettingsModel();
enabled.setValue(true);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folderC).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).usingRuleSetting(IS_INHERITANCE_ENABLED).updateSetting(enabled);
STEP("Link folderA to ruleSetD");
RestRuleSetLinkModel linkModel = new RestRuleSetLinkModel();
linkModel.setId(folderD.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folderA).createRuleLink(linkModel);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folderA).createRuleLink(linkModel);
STEP("Get the rule sets for the folderD");
List<RestRuleSetModel> ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(folderD).getListOfRuleSets().getEntries();
List<RestRuleSetModel> ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(folderD).getListOfRuleSets().getEntries();
STEP("Check the rules for each rule set are as expected");
List<RestRuleModel> expectedRuleIds = List.of(ruleD, ruleB, ruleC);
IntStream.range(0, 2).forEach(index -> {
String ruleSetId = ruleSets.get(index).onModel().getId();
List<RestRuleModel> rules = restClient.authenticateUser(user)
.withCoreAPI()
.withPrivateAPI()
.usingNode(folderD)
.usingRuleSet(ruleSetId)
.getListOfRules()

View File

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

View File

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

View File

@@ -27,16 +27,19 @@ package org.alfresco.rest.rules;
import static java.util.stream.Collectors.toList;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.OK;
import java.util.List;
import java.util.stream.IntStream;
import com.google.common.collect.Lists;
import org.alfresco.rest.RestTest;
import org.alfresco.rest.model.RestRuleModel;
import org.alfresco.rest.model.RestRuleSetModel;
import org.alfresco.utility.constants.UserRole;
import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
@@ -64,17 +67,137 @@ public class ReorderRules extends RestTest
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = IntStream.range(0, 3).mapToObj(index -> {
RestRuleModel ruleModel = createRuleModel("ruleName");
return restClient.authenticateUser(user).withCoreAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
}).collect(toList());
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Get the default rule set for the folder including the ordered rule ids");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(folder)
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").getDefaultRuleSet();
List<String> expectedRuleIds = rules.stream().map(RestRuleModel::getId).collect(toList());
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(expectedRuleIds);
}
/** Check that a user can view the order of the rules in a rule set if they only have read permission. */
@Test
public void getRuleSetAndRuleIdsWithReadOnlyPermission()
{
STEP("Create a site owned by admin and add user as a consumer");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteConsumer);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Get the rule set with the ordered list of rules");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").getDefaultRuleSet();
restClient.assertStatusCodeIs(OK);
List<String> ruleIds = rules.stream().map(RestRuleModel::getId).collect(toList());
ruleSet.assertThat().field("ruleIds").is(ruleIds);
}
/** Check we can reorder the rules in a rule set. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void reorderRules()
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Reverse the order of the rules within the rule set");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Check we can reorder the rules in a rule set by editing the response from the GET. */
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void reorderRulesUsingResponseFromGET()
{
STEP("Create a folder containing three rules in the existing site");
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
List<RestRuleModel> rules = createRulesInFolder(folder, user);
STEP("Get the rule set with its id.");
RestRuleSetModel ruleSetResponse = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").getDefaultRuleSet();
STEP("Reverse the order of the rules within the rule set");
ruleSetResponse.setRuleIds(Lists.reverse(ruleSetResponse.getRuleIds()));
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder)
.include("ruleIds").updateRuleSet(ruleSetResponse);
restClient.assertStatusCodeIs(OK);
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Check that a user cannot reorder the rules in a rule set if they only have read permission. */
@Test
public void reorderRulesWithoutPermission()
{
STEP("Create a site owned by admin and add user as a consumer");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteContributor);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Try to reorder the rules as the contributor");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/** Check that a user can reorder the rules in a rule set if they have write permission. */
@Test
public void reorderRulesWithPermission()
{
STEP("Create a site owned by admin and add user as a collaborator");
SiteModel siteModel = dataSite.usingAdmin().createPrivateRandomSite();
dataUser.addUserToSite(user, siteModel, UserRole.SiteCollaborator);
STEP("Use admin to create a folder with a rule set and three rules in it");
FolderModel ruleFolder = dataContent.usingAdmin().usingSite(siteModel).createFolder();
dataContent.usingAdmin().usingResource(ruleFolder).createFolder();
List<RestRuleModel> rules = createRulesInFolder(ruleFolder, dataUser.getAdminUser());
STEP("Try to reorder the rules as the contributor");
List<String> reversedRuleIds = Lists.reverse(rules.stream().map(RestRuleModel::getId).collect(toList()));
RestRuleSetModel ruleSetBody = new RestRuleSetModel();
ruleSetBody.setId("-default-");
ruleSetBody.setRuleIds(reversedRuleIds);
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("ruleIds").updateRuleSet(ruleSetBody);
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("ruleIds").is(reversedRuleIds);
}
/** Create three rules in the given folder. */
private List<RestRuleModel> createRulesInFolder(FolderModel folder, UserModel user)
{
return IntStream.range(0, 3).mapToObj(index ->
{
RestRuleModel ruleModel = rulesUtils.createRuleModelWithDefaultValues();
return restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).usingDefaultRuleSet().createSingleRule(ruleModel);
}).collect(toList());
}
}

View File

@@ -25,9 +25,14 @@
*/
package org.alfresco.rest.rules;
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
import static org.alfresco.utility.constants.UserRole.SiteConsumer;
import static org.alfresco.utility.report.log.Step.STEP;
import static org.springframework.http.HttpStatus.*;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.NO_CONTENT;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.dataprep.CMISUtil;
import org.alfresco.rest.RestTest;
@@ -41,6 +46,7 @@ import org.alfresco.utility.model.FolderModel;
import org.alfresco.utility.model.SiteModel;
import org.alfresco.utility.model.TestGroup;
import org.alfresco.utility.model.UserModel;
import org.springframework.http.HttpStatus;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -72,12 +78,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -85,7 +91,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a rule folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -94,7 +100,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -102,7 +108,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
@@ -125,12 +131,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -138,7 +144,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a rule set");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleSetId);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -147,7 +153,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -155,7 +161,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection likedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection likedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(folder)
.include("inclusionType")
.getListOfRuleSets();
@@ -167,6 +173,55 @@ public class RuleSetLinksTests extends RestTest
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we can link to a rule set when linking from a folder which has inherited rules.
*/
@Test(groups = {TestGroup.REST_API, TestGroup.RULES})
public void linkFromFolderWithInheritedRules()
{
STEP("Create folders");
final FolderModel parentFolder = dataContent.usingUser(user).usingSite(site).createFolder();
final FolderModel childFolder = dataContent.usingUser(user).usingResource(parentFolder).createFolder();
final FolderModel linkedToFolder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create rules in the parent folder and the linking folder");
RestRuleModel parentRule = rulesUtils.createInheritableRuleModel();
parentRule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet().createSingleRule(parentRule);
restClient.assertStatusCodeIs(CREATED);
RestRuleModel linkingFolderRule = rulesUtils.createRuleModelWithDefaultValues();
restClient.authenticateUser(user).withPrivateAPI().usingNode(linkedToFolder).usingDefaultRuleSet().createSingleRule(linkingFolderRule);
restClient.assertStatusCodeIs(CREATED);
STEP("Get the rule sets for the linking folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(linkedToFolder).getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
STEP("Link the child folder to the target folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(linkedToFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
STEP("Assert link result");
final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
expectedLink.setId(ruleSetId);
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Assert that the child folder has also inherited the parent rule");
RestRuleSetModelsCollection ruleSetsInh = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).include("inclusionType").getListOfRuleSets();
restClient.assertStatusCodeIs(OK);
String inheritedRuleSetId = ruleSetsInh.getEntries().stream()
.filter(ruleSet -> ruleSet.onModel().getInclusionType().equals("inherited"))
.findFirst().get().onModel().getId();
RestRuleModelsCollection inheritedRules = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).usingRuleSet(inheritedRuleSetId).getListOfRules();
restClient.assertStatusCodeIs(OK);
inheritedRules.assertThat().entriesListContains("id", parentRule.getId())
.and().entriesListCountIs(1);
}
/**
* Check we get 404 when linking to a non-existing rule set/folder.
@@ -180,7 +235,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to non-existing rule set");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId("dummy-rule-set-id");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result is 404");
restClient.assertStatusCodeIs(NOT_FOUND);
@@ -199,7 +254,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a folder without rules");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(folder2.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -217,17 +272,17 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder2 = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create rules in both folders.");
RestRuleModel ruleModel1 = createRuleModel("ruleName1");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).usingDefaultRuleSet()
RestRuleModel ruleModel1 = rulesUtils.createRuleModel("ruleName1");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).usingDefaultRuleSet()
.createSingleRule(ruleModel1);
RestRuleModel ruleModel2 = createRuleModel("ruleName2");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder2).usingDefaultRuleSet()
RestRuleModel ruleModel2 = rulesUtils.createRuleModel("ruleName2");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder2).usingDefaultRuleSet()
.createSingleRule(ruleModel2);
STEP("Link from a folder with rules");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(folder2.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder1).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -248,7 +303,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a file node");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(fileContent.getNodeRef());
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Assert link result is 400");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -266,12 +321,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel childFolder = dataContent.usingUser(user).usingSite(site).usingResource(parentFolder).createFolder();
STEP("Create a rule in the parent folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(parentFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -279,7 +334,7 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to the parent folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(parentFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(childFolder).createRuleLink(request);
STEP("Assert link result");
restClient.assertStatusCodeIs(CREATED);
@@ -288,7 +343,7 @@ public class RuleSetLinksTests extends RestTest
ruleLink.assertThat().isEqualTo(expectedLink);
STEP("Check if child folder returns same rules");
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(childFolder)
.usingDefaultRuleSet()
.getListOfRules();
@@ -296,7 +351,7 @@ public class RuleSetLinksTests extends RestTest
linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
STEP("Check if child folder returns rule set with linked inclusionType");
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withPrivateAPI()
.usingNode(childFolder)
.include("inclusionType")
.getListOfRuleSets();
@@ -308,6 +363,51 @@ public class RuleSetLinksTests extends RestTest
.get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
}
/**
* Check we get an error when trying to link to a rule set that we can't view.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void linkToRuleSetWithoutPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Use a normal user to try to link to the rule.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(FORBIDDEN);
}
/**
* Check we are able to link to a rule set with only read permission.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void linkToRuleSetWithOnlyReadPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the normal user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use a normal user to try to link to the rule.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
}
/**
* Check we can DELETE/unlink a ruleset
*
@@ -321,12 +421,12 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Create a rule in the rule folder.");
RestRuleModel ruleModel = createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
RestRuleModel ruleModel = rulesUtils.createRuleModel("ruleName");
RestRuleModel rule = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder).usingDefaultRuleSet()
.createSingleRule(ruleModel);
STEP("Get the rule sets for the folder and find the rule set id");
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.getListOfRuleSets();
ruleSets.assertThat().entriesListCountIs(1);
final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
@@ -334,23 +434,23 @@ public class RuleSetLinksTests extends RestTest
STEP("Link to a rule folder");
final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(ruleFolder.getNodeRef());
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).createRuleLink(request);
STEP("Unlink the rule set");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).unlinkRuleSet(ruleSetId);
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet(ruleSetId);
STEP("Assert unlink result");
restClient.assertStatusCodeIs(NO_CONTENT);
STEP("GET the rule set and isLinkedTo field.");
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
RestRuleSetModel ruleSet = restClient.authenticateUser(user).withPrivateAPI().usingNode(ruleFolder)
.include("isLinkedTo", "linkedToBy", "owningFolder")
.getDefaultRuleSet();
STEP("Assert linkedTo is false.");
restClient.assertStatusCodeIs(OK);
ruleSet.assertThat().field("isLinkedTo").is(false)
.assertThat().field("linkedToBy").isEmpty();;
.assertThat().field("linkedToBy").isEmpty();
}
/**
@@ -365,7 +465,7 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt to unlink the rule set");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).unlinkRuleSet(folder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet(folder.getNodeRef());
STEP("Assert unlink result");
restClient.assertStatusCodeIs(BAD_REQUEST)
@@ -385,10 +485,69 @@ public class RuleSetLinksTests extends RestTest
final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
STEP("Attempt to unlink the rule set");
restClient.authenticateUser(user).withCoreAPI().usingNode(folder).unlinkRuleSet("non-existent-id");
restClient.authenticateUser(user).withPrivateAPI().usingNode(folder).unlinkRuleSet("non-existent-id");
STEP("Assert unlink result");
restClient.assertStatusCodeIs(NOT_FOUND)
.assertLastError().containsSummary("The entity with id:");
.assertLastError().containsSummary("Rule set with id non-existent-id was not found");
}
/**
* Check we cannot unlink from a rule set that we can't view.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void unlinkFromRuleSetWithoutPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use the consumer to create a folder with a link to the private rule set.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
STEP("Remove the user from the private site.");
dataUser.usingAdmin().removeUserFromSite(user, privateSite);
STEP("Use the user to try to unlink from the rule set.");
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).unlinkRuleSet("-default-");
restClient.assertStatusCodeIs(FORBIDDEN);
}
/**
* Check we can unlink from a rule set if we only have read permission for it.
*/
@Test (groups = { TestGroup.REST_API, TestGroup.RULES })
public void unlinkFromRuleSetWithOnlyReadPermission()
{
STEP("Use admin to create a private site with a folder containing a rule.");
SiteModel privateSite = dataSite.usingAdmin().createPrivateRandomSite();
FolderModel privateFolder = dataContent.usingAdmin().usingSite(privateSite).createFolder();
restClient.authenticateUser(dataUser.getAdminUser()).withPrivateAPI().usingNode(privateFolder).usingDefaultRuleSet()
.createSingleRule(rulesUtils.createRuleModelWithDefaultValues());
STEP("Add the user as a consumer.");
dataUser.usingAdmin().addUserToSite(user, privateSite, SiteConsumer);
STEP("Use the consumer to create a folder with a link to the private rule set.");
FolderModel publicFolder = dataContent.usingUser(user).usingSite(site).createFolder();
RestRuleSetLinkModel request = new RestRuleSetLinkModel();
request.setId(privateFolder.getNodeRef());
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).createRuleLink(request);
restClient.assertStatusCodeIs(CREATED);
STEP("Use the consumer to try to unlink from the rule set.");
restClient.authenticateUser(user).withPrivateAPI().usingNode(publicFolder).unlinkRuleSet("-default-");
restClient.assertStatusCodeIs(NO_CONTENT);
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,6 @@
<html>
<head></head>
<body>
Hello ${args.name}!
</body>
</html>

View File

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

View File

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

View File

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

View File

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

45
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.147</version>
<version>20.28-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Alfresco Community Repo Parent</name>
@@ -24,7 +24,7 @@
<properties>
<acs.version.major>7</acs.version.major>
<acs.version.minor>3</acs.version.minor>
<acs.version.minor>4</acs.version.minor>
<acs.version.revision>0</acs.version.revision>
<acs.version.label />
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
@@ -51,20 +51,19 @@
<dependency.alfresco-log-sanitizer.version>0.2</dependency.alfresco-log-sanitizer.version>
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
<dependency.activiti.version>5.23.0</dependency.activiti.version>
<dependency.alfresco-transform-service.version>2.0.0-A3</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0-A3</dependency.alfresco-transform-core.version>
<dependency.alfresco-greenmail.version>6.4</dependency.alfresco-greenmail.version>
<dependency.alfresco-transform-service.version>2.0.0</dependency.alfresco-transform-service.version>
<dependency.alfresco-transform-core.version>3.0.0</dependency.alfresco-transform-core.version>
<dependency.alfresco-greenmail.version>6.5</dependency.alfresco-greenmail.version>
<dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
<dependency.spring.version>5.3.23</dependency.spring.version>
<dependency.antlr.version>3.5.3</dependency.antlr.version>
<dependency.jackson.version>2.13.3</dependency.jackson.version>
<dependency.jackson-databind.version>2.13.3</dependency.jackson-databind.version>
<dependency.cxf.version>3.5.3</dependency.cxf.version>
<dependency.jackson.version>2.14.0</dependency.jackson.version>
<dependency.cxf.version>3.5.4</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.webscripts.version>8.32</dependency.webscripts.version>
<dependency.bouncycastle.version>1.70</dependency.bouncycastle.version>
<dependency.mockito-core.version>4.6.1</dependency.mockito-core.version>
<dependency.mockito-core.version>4.9.0</dependency.mockito-core.version>
<dependency.assertj.version>3.23.1</dependency.assertj.version>
<dependency.org-json.version>20220320</dependency.org-json.version>
<dependency.commons-dbcp.version>2.9.0</dependency.commons-dbcp.version>
@@ -78,10 +77,10 @@
<dependency.gytheio.version>0.17</dependency.gytheio.version>
<dependency.groovy.version>3.0.12</dependency.groovy.version>
<dependency.tika.version>2.4.1</dependency.tika.version>
<dependency.spring-security.version>5.7.3</dependency.spring-security.version>
<dependency.spring-security.version>5.7.5</dependency.spring-security.version>
<dependency.truezip.version>7.7.10</dependency.truezip.version>
<dependency.poi.version>5.2.2</dependency.poi.version>
<dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
<dependency.poi-ooxml-lite.version>5.2.3</dependency.poi-ooxml-lite.version>
<dependency.keycloak.version>18.0.0</dependency.keycloak.version>
<dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
<dependency.camel.version>3.18.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
@@ -89,11 +88,11 @@
<dependency.netty.qpid.version>4.1.72.Final</dependency.netty.qpid.version> <!-- must be in sync with camels transitive dependencies: native-unix-common/native-epoll/native-kqueue -->
<dependency.netty-tcnative.version>2.0.53.Final</dependency.netty-tcnative.version> <!-- must be in sync with camels transitive dependencies -->
<dependency.activemq.version>5.17.1</dependency.activemq.version>
<dependency.apache-compress.version>1.21</dependency.apache-compress.version>
<dependency.apache-compress.version>1.22</dependency.apache-compress.version>
<dependency.apache.taglibs.version>1.2.5</dependency.apache.taglibs.version>
<dependency.awaitility.version>4.2.0</dependency.awaitility.version>
<dependency.swagger-ui.version>3.38.0</dependency.swagger-ui.version>
<dependency.swagger-parser.version>1.0.61</dependency.swagger-parser.version>
<dependency.swagger-parser.version>1.0.63</dependency.swagger-parser.version>
<dependency.maven-filtering.version>3.1.1</dependency.maven-filtering.version>
<dependency.maven-artifact.version>3.8.6</dependency.maven-artifact.version>
<dependency.jdom2.version>2.0.6.1</dependency.jdom2.version>
@@ -110,9 +109,9 @@
<dependency.jakarta-json-path.version>2.7.0</dependency.jakarta-json-path.version>
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
<alfresco.googledrive.version>3.2.3-A3</alfresco.googledrive.version>
<alfresco.aos-module.version>1.4.1</alfresco.aos-module.version>
<alfresco.api-explorer.version>7.3.0-A1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.googledrive.version>3.3.1-A3</alfresco.googledrive.version>
<alfresco.aos-module.version>1.5.0</alfresco.aos-module.version>
<alfresco.api-explorer.version>7.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
@@ -123,8 +122,8 @@
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
<dependency.tas-utility.version>3.0.56</dependency.tas-utility.version>
<dependency.rest-assured.version>5.2.0</dependency.rest-assured.version>
<dependency.tas-restapi.version>1.127</dependency.tas-restapi.version>
<dependency.tas-email.version>1.9</dependency.tas-email.version>
<dependency.tas-restapi.version>1.135</dependency.tas-restapi.version>
<dependency.tas-email.version>1.11</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>
@@ -150,7 +149,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.147</tag>
<tag>HEAD</tag>
</scm>
<distributionManagement>
@@ -503,7 +502,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${dependency.jackson-databind.version}</version>
<version>${dependency.jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
@@ -652,7 +651,7 @@
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>7.5.3</version>
<version>7.5.4</version>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>
@@ -737,7 +736,7 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.11.1</version>
<version>2.12.1</version>
</dependency>
<!-- provided dependencies -->
@@ -937,7 +936,7 @@
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -64,6 +64,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
static final String FIELD_NOT_NULL = "Field in condition must not be blank";
static final String PARAMETER_NOT_NULL = "Parameter in condition must not be blank";
static final String COMPARATOR_NOT_NULL = "Comparator in condition must not be blank";
static final String INVALID_COMPARATOR_VALUE = "Comparator value for condition is invalid: %s";
private final NamespaceService namespaceService;
private final Nodes nodes;
@@ -157,13 +158,23 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
parameterValues.put(ComparePropertyValueEvaluator.PARAM_PROPERTY, QName.createQName(field, namespaceService));
}
checkStringNotBlank(restModel.getComparator(), COMPARATOR_NOT_NULL);
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, restModel.getComparator().toUpperCase());
parameterValues.put(ComparePropertyValueEvaluator.PARAM_OPERATION, getComparatorValue(restModel.getComparator()));
parameterValues.put(ComparePropertyValueEvaluator.PARAM_VALUE, parameter);
break;
}
return new ActionConditionImpl(UUID.randomUUID().toString(), conditionDefinitionId, parameterValues);
}
private String getComparatorValue(String comparator)
{
try
{
return ComparePropertyValueOperation.valueOf(comparator.toUpperCase()).toString();
} catch (IllegalArgumentException e) {
throw new InvalidArgumentException(String.format(INVALID_COMPARATOR_VALUE, comparator));
}
}
private void checkStringNotBlank(final String string, final String message) {
if (Strings.isBlank(string))
{

View File

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

View File

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

View File

@@ -54,9 +54,9 @@ public class RuleSetLoader
protected static final String IS_LINKED_TO = "isLinkedTo";
protected static final String RULE_IDS = "ruleIds";
private static final int MAX_INHERITED_BY_SIZE = 100;
private static final int MAX_LINKED_TO_BY_SIZE = 100;
private NodeService nodeService;
private RuleService ruleService;
private RestRuleModelMapper restRuleModelMapper;
/**
* Load a rule set for the given node ref.
@@ -123,7 +123,7 @@ public class RuleSetLoader
private List<NodeRef> loadLinkedToBy(NodeRef ruleSetNodeRef)
{
return ruleService.getFoldersLinkingToRuleSet(ruleSetNodeRef);
return ruleService.getFoldersLinkingToRuleSet(ruleSetNodeRef, MAX_LINKED_TO_BY_SIZE);
}
private boolean loadIsInherited(NodeRef ruleSetNodeRef)
@@ -148,7 +148,7 @@ public class RuleSetLoader
);
}
private List<String> loadRuleIds(NodeRef folderNodeRef)
public List<String> loadRuleIds(NodeRef folderNodeRef)
{
return ruleService.getRules(folderNodeRef, false).stream()
.map(org.alfresco.service.cmr.rule.Rule::getNodeRef)
@@ -166,8 +166,4 @@ public class RuleSetLoader
this.ruleService = ruleService;
}
public void setRestRuleModelMapper(RestRuleModelMapper restRuleModelMapper)
{
this.restRuleModelMapper = restRuleModelMapper;
}
}

View File

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

View File

@@ -26,41 +26,47 @@
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.repo.action.ActionImpl;
import org.alfresco.repo.action.access.ActionAccessRestriction;
import org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter;
import org.alfresco.rest.api.Rules;
import org.alfresco.rest.api.model.mapper.RestModelMapper;
import org.alfresco.rest.api.model.rules.CompositeCondition;
import org.alfresco.rest.api.model.rules.InclusionType;
import org.alfresco.rest.api.model.rules.Rule;
import org.alfresco.rest.api.model.rules.RuleExecution;
import org.alfresco.rest.api.model.rules.RuleSet;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.api.model.rules.SimpleCondition;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.ListPage;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.service.Experimental;
import org.alfresco.service.cmr.action.ActionCondition;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.util.collections.CollectionUtils;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.GUID;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
@Experimental
public class RulesImpl implements Rules
{
private static final Logger LOGGER = LoggerFactory.getLogger(RulesImpl.class);
private static final String MUST_HAVE_AT_LEAST_ONE_ACTION = "A rule must have at least one action";
private ActionService actionService;
private RuleService ruleService;
private NodeValidator validator;
private RuleLoader ruleLoader;
private RuleSetLoader ruleSetLoader;
private ActionPermissionValidator actionPermissionValidator;
private RestModelMapper<Rule, org.alfresco.service.cmr.rule.Rule> ruleMapper;
@@ -73,8 +79,10 @@ public class RulesImpl implements Rules
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
NodeRef owningFolder = ruleService.getOwningNodeRef(ruleSetNode);
RuleSet ruleSet = ruleSetLoader.loadRuleSet(ruleSetNode, folderNodeRef, List.of(INCLUSION_TYPE));
final List<Rule> rules = ruleService.getRules(owningFolder, false).stream()
.filter(ruleModel -> ruleSet.getInclusionType() != InclusionType.INHERITED || ruleModel.isAppliedToChildren())
.map(ruleModel -> ruleLoader.loadRule(ruleModel, includes))
.collect(Collectors.toList());
@@ -130,6 +138,25 @@ public class RulesImpl implements Rules
ruleService.removeRule(folderNodeRef, rule);
}
@Override
public RuleExecution executeRules(final String folderNodeId, final boolean eachSubFolderIncluded)
{
final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
final Map<String, Serializable> parameterValues = new HashMap<>();
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_RUN_ALL_RULES_ON_CHILDREN, eachSubFolderIncluded);
parameterValues.put(ExecuteAllRulesActionExecuter.PARAM_EXECUTE_INHERITED_RULES, true);
final ActionImpl action = new ActionImpl(null, GUID.generate(), ExecuteAllRulesActionExecuter.NAME);
action.setNodeRef(folderNodeRef);
action.setParameterValues(parameterValues);
ActionAccessRestriction.setActionContext(action, ActionAccessRestriction.V1_ACTION_CONTEXT);
actionService.executeAction(action, folderNodeRef, true, false);
return RuleExecution.builder()
.eachSubFolderIncluded(eachSubFolderIncluded)
.create();
}
private org.alfresco.service.cmr.rule.Rule mapToServiceModelAndValidateActions(Rule rule)
{
if (CollectionUtils.isEmpty(rule.getActions()))
@@ -141,6 +168,11 @@ public class RulesImpl implements Rules
return actionPermissionValidator.validateRulePermissions(serviceModelRule);
}
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
public void setRuleService(RuleService ruleService)
{
this.ruleService = ruleService;
@@ -156,6 +188,11 @@ public class RulesImpl implements Rules
this.ruleLoader = ruleLoader;
}
public void setRuleSetLoader(RuleSetLoader ruleSetLoader)
{
this.ruleSetLoader = ruleSetLoader;
}
public void setActionPermissionValidator(ActionPermissionValidator actionPermissionValidator)
{
this.actionPermissionValidator = actionPermissionValidator;

View File

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

View File

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

View File

@@ -32,7 +32,7 @@ public class Action
private String id;
private String actionDefinitionId;
private String targetId;
Map<String, String> params;
private Map<String, ?> params;
public String getId()
{
@@ -64,12 +64,12 @@ public class Action
this.targetId = targetId;
}
public Map<String, String> getParams()
public Map<String, ?> getParams()
{
return params;
}
public void setParams(Map<String, String> params)
public void setParams(Map<String, ? extends Object> params)
{
this.params = params;
}

View File

@@ -0,0 +1,99 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model;
import java.util.List;
import org.alfresco.service.Experimental;
/**
* Representation of action parameter constraint.
* Helps to constraint the list of allowable values for an action parameter.
* When action parameter has constraints defined (@see ActionDefinition.ParameterDefinition#getParameterConstraintName())
* they will be listed here.
*
* @author mpichura
*/
@Experimental
public class ActionParameterConstraint
{
/**
* Constraint name.
*/
private String constraintName;
/**
* List of objects representing constraint values along with additional data
*/
private List<ConstraintData> constraintValues;
public List<ConstraintData> getConstraintValues()
{
return constraintValues;
}
public void setConstraintValues(List<ConstraintData> constraintValues)
{
this.constraintValues = constraintValues;
}
public String getConstraintName()
{
return constraintName;
}
public void setConstraintName(String constraintName)
{
this.constraintName = constraintName;
}
public static class ConstraintData
{
public ConstraintData(final String value, final String label)
{
this.value = value;
this.label = label;
}
/**
* Actual constraint value
*/
private String value;
/**
* A label associated to constraint's value
*/
private String label;
public String getValue()
{
return value;
}
public String getLabel()
{
return label;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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