mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-29 15:21:53 +00:00
Compare commits
1 Commits
23.1.0.133
...
feature/AC
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f02b17e4b |
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@@ -53,6 +53,24 @@ updates:
|
||||
- dependency-name: org.freemarker:freemarker
|
||||
versions:
|
||||
- "> 2.3.20-alfresco-patched-20200421"
|
||||
- dependency-name: org.keycloak:keycloak-adapter-core
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.keycloak:keycloak-adapter-spi
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.keycloak:keycloak-authz-client
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.keycloak:keycloak-common
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.keycloak:keycloak-core
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.keycloak:keycloak-servlet-adapter-spi
|
||||
versions:
|
||||
- "> 12.0.2"
|
||||
- dependency-name: org.eclipse.jetty:jetty-server
|
||||
versions:
|
||||
- 9.4.38.v20210224
|
||||
|
||||
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@@ -23,7 +23,6 @@ env:
|
||||
MAVEN_USERNAME: ${{ secrets.NEXUS_USERNAME }}
|
||||
QUAY_PASSWORD: ${{ secrets.QUAY_PASSWORD }}
|
||||
QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }}
|
||||
CI_WORKSPACE: ${{ github.workspace }}
|
||||
TAS_ENVIRONMENT: ./packaging/tests/environment
|
||||
TAS_SCRIPTS: ../alfresco-community-repo/packaging/tests/scripts
|
||||
|
||||
@@ -314,11 +313,6 @@ jobs:
|
||||
- testSuite: SearchTestSuite
|
||||
compose-profile: default
|
||||
mvn-options: '-Dindex.subsystem.name=solr6'
|
||||
- testSuite: MTLSTestSuite
|
||||
compose-profile: with-mtls-transform-core-aio
|
||||
mtls: true
|
||||
disabledHostnameVerification: false
|
||||
mvn-options: '-Dencryption.ssl.keystore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.keystore -Dencryption.ssl.truststore.location=${CI_WORKSPACE}/keystores/alfresco/alfresco.truststore'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.33.0
|
||||
@@ -327,17 +321,6 @@ jobs:
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- name: "Set transformers tag"
|
||||
run: echo "TRANSFORMERS_TAG=$(mvn help:evaluate -Dexpression=dependency.alfresco-transform-core.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||
- name: "Generate Keystores and Truststores for Mutual TLS configuration"
|
||||
if: ${{ matrix.mtls }}
|
||||
run: |
|
||||
git clone -b "master" --depth=1 "https://${{ secrets.BOT_GITHUB_USERNAME }}:${{ secrets.BOT_GITHUB_TOKEN }}@github.com/Alfresco/alfresco-ssl-generator.git"
|
||||
if ${{ matrix.disabledHostnameVerification }} ; then
|
||||
bash ${{ env.CI_WORKSPACE }}/alfresco-ssl-generator/scripts/ci/generate_keystores_wrong_hostnames.sh
|
||||
echo "HOSTNAME_VERIFICATION_DISABLED=true" >> "$GITHUB_ENV"
|
||||
else
|
||||
bash ${{ env.CI_WORKSPACE }}/alfresco-ssl-generator/scripts/ci/generate_keystores.sh
|
||||
echo "HOSTNAME_VERIFICATION_DISABLED=false" >> "$GITHUB_ENV"
|
||||
fi
|
||||
- name: "Set up the environment"
|
||||
run: |
|
||||
if [ -e ./scripts/ci/tests/${{ matrix.testSuite }}-setup.sh ]; then
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
@@ -82,7 +82,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.2.13</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -50,7 +50,6 @@ import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Ignore;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.AssertJUnit;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
@@ -136,195 +135,192 @@ public class DispositionScheduleLinkedRecordsTest extends BaseRMRestTest {
|
||||
* <p>
|
||||
* <p/> TestRail Test C775<p/>
|
||||
**/
|
||||
// @Ignore("ACS-5020")
|
||||
// @Test
|
||||
// @AlfrescoTest(jira = "RM-1622")
|
||||
// public void dispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
// STEP("Create record category");
|
||||
// Category1 = createRootCategory(categoryRM3077);
|
||||
//
|
||||
// //create retention schedule
|
||||
// dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
|
||||
//
|
||||
// // add cut off step
|
||||
// dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
|
||||
//
|
||||
// //create a copy of the category recordsCategory
|
||||
// String CopyCategoryId = copyCategory(getAdminUser(),Category1.getId(), copyCategoryRM3077);
|
||||
//
|
||||
// // create folders in both categories
|
||||
// CatFolder = createRecordFolder(Category1.getId(), folderRM3077);
|
||||
// CopyCatFolder = createRecordFolder(CopyCategoryId, copyFolderRM3077);
|
||||
//
|
||||
// // create record files
|
||||
// String electronicRecord = "RM-2801 electronic record";
|
||||
// Record elRecord = createElectronicRecord(CatFolder.getId(), electronicRecord);
|
||||
// String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), electronicRecord);
|
||||
//
|
||||
// String nonElectronicRecord = "RM-2801 non-electronic record";
|
||||
// Record nonElRecord = createNonElectronicRecord(CatFolder.getId(), nonElectronicRecord);
|
||||
// String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), nonElectronicRecord);
|
||||
//
|
||||
// // link the records to copy folder, then complete them
|
||||
// List<String> recordLists = new ArrayList<>();
|
||||
// recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + elRecord.getId());
|
||||
// recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + nonElRecord.getId());
|
||||
//
|
||||
// linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,copyCategoryRM3077 + "/" +
|
||||
// copyFolderRM3077, recordLists);
|
||||
// recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), elRecordFullName);
|
||||
// recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), nonElRecordFullName);
|
||||
//
|
||||
// // edit disposition date
|
||||
// recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),editDispositionDateJson(),CatFolder.getName());
|
||||
//
|
||||
// // cut off the Folder
|
||||
// recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),CatFolder.getName());
|
||||
//
|
||||
// // Verify the Content
|
||||
// Node electronicNode = getNode(elRecord.getId());
|
||||
// assertTrue("The content of " + electronicRecord + " is available",
|
||||
// StringUtils.isEmpty(electronicNode.getNodeContent().getResponse().getBody().asString()));
|
||||
//
|
||||
// // verify the Properties
|
||||
// AssertJUnit.assertNull("The properties are present even after cutting off the record.", elRecord.getProperties().getTitle());
|
||||
//
|
||||
// // delete precondition
|
||||
// deleteRecordCategory(Category1.getId());
|
||||
// deleteRecordCategory(CopyCategoryId);
|
||||
// }
|
||||
// /**
|
||||
// * Test covering RM-3060
|
||||
// * Check the disposition steps for a record can be executed
|
||||
// * When the record is linked to a folder with the same disposition schedule
|
||||
// * */
|
||||
// @Ignore("ACS-5020")
|
||||
//// @Test
|
||||
// @AlfrescoTest (jira = "RM-3060")
|
||||
// public void sameDispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
//
|
||||
// // create a category with retention applied on records level
|
||||
// RecordCategory recordCategory = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
// .createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
|
||||
// RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
// dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
|
||||
// dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "week|1", DATE_FILED);
|
||||
// dispositionScheduleService.addTransferAfterEventStep(firstCategoryRM3060, TRANSFER_LOCATION, RMEvents.CASE_CLOSED.getEventName());
|
||||
// dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(firstCategoryRM3060, "week|1", CUT_OFF_DATE);
|
||||
//
|
||||
// // make a copy of the category created
|
||||
// String categorySecondId = copyCategory(getAdminUser(), recordCategory.getId(), secondCategoryRM3060);
|
||||
//
|
||||
// // create a folder on the category firstCategoryRM3060 with a complete electronic record
|
||||
// RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(recordCategory.getId(),firstFolderRM3060);
|
||||
// Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
|
||||
//
|
||||
// String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
|
||||
// String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
//
|
||||
// recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(), elRecordFullName);
|
||||
//
|
||||
// // create a folder on the category secondCategoryRM3060 with a non electronic record
|
||||
// RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(categorySecondId,secondFolderRM3060);
|
||||
// Record secondNonElectronicRecord = createNonElectronicRecord(secondFolderRecordCategoryChild.getId(),nonElectronicRecordRM3060);
|
||||
//
|
||||
// // link the nonElectronicRecordRM3060 to firstFolderRM3060
|
||||
// List<String> recordLists = new ArrayList<>();
|
||||
// recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
//
|
||||
// linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
// secondFolderRM3060, recordLists);
|
||||
// String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), secondFolderRM3060, secondNonElectronicRecord.getName());
|
||||
// String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060);
|
||||
//
|
||||
// // complete records and cut them off
|
||||
// recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(), nonElRecordFullName);
|
||||
//
|
||||
// // edit the disposition date
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
//
|
||||
// // cut off the record
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
|
||||
//
|
||||
// //check the record is cut off
|
||||
// AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
//
|
||||
// // link the electronic record to secondFolderRM3060
|
||||
// recordLists.clear();
|
||||
// recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
// linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
// getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
// secondFolderRM3060, recordLists);
|
||||
//
|
||||
// // edit the disposition date and cut off the record
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
|
||||
//
|
||||
// AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
//
|
||||
// // open the record and complete the disposition schedule event
|
||||
// rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(), elRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
// rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(), nonElRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
//
|
||||
// // transfer the files & complete transfers
|
||||
// HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060));
|
||||
//
|
||||
// String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
|
||||
//
|
||||
// HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
// getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060));
|
||||
//
|
||||
// String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
|
||||
//
|
||||
// AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully transferred", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
// AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully transferred.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
//
|
||||
// // edit the disposition date for nonElectronicRecordRM3060 & electronicRecordRM3060
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
//
|
||||
// // destroy nonElectronicRecordRM3060 & electronicRecordRM3060 records
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
|
||||
// recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
// getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
|
||||
//
|
||||
// // check the file is not displayed
|
||||
// assertNull("The file " + nonElectronicRecordRM3060 + " has not been successfully destroyed.", secondNonElectronicRecord.getContent());
|
||||
// assertNull("The file " + electronicRecordRM3060 + " has not been successfully destroyed.", firstElectronicRecord.getContent());
|
||||
//
|
||||
// // delete precondition
|
||||
// deleteRecordCategory(recordCategory.getId());
|
||||
// deleteRecordCategory(categorySecondId);
|
||||
// }
|
||||
@Test
|
||||
@AlfrescoTest(jira = "RM-1622")
|
||||
public void dispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
STEP("Create record category");
|
||||
Category1 = createRootCategory(categoryRM3077);
|
||||
|
||||
//create retention schedule
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(Category1.getName(), false);
|
||||
|
||||
// add cut off step
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(Category1.getName(), "day|2", CREATED_DATE);
|
||||
|
||||
//create a copy of the category recordsCategory
|
||||
String CopyCategoryId = copyCategory(getAdminUser(),Category1.getId(), copyCategoryRM3077);
|
||||
|
||||
// create folders in both categories
|
||||
CatFolder = createRecordFolder(Category1.getId(), folderRM3077);
|
||||
CopyCatFolder = createRecordFolder(CopyCategoryId, copyFolderRM3077);
|
||||
|
||||
// create record files
|
||||
String electronicRecord = "RM-2801 electronic record";
|
||||
Record elRecord = createElectronicRecord(CatFolder.getId(), electronicRecord);
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), electronicRecord);
|
||||
|
||||
String nonElectronicRecord = "RM-2801 non-electronic record";
|
||||
Record nonElRecord = createNonElectronicRecord(CatFolder.getId(), nonElectronicRecord);
|
||||
String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), CatFolder.getName(), nonElectronicRecord);
|
||||
|
||||
// link the records to copy folder, then complete them
|
||||
List<String> recordLists = new ArrayList<>();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + elRecord.getId());
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + nonElRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,copyCategoryRM3077 + "/" +
|
||||
copyFolderRM3077, recordLists);
|
||||
recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), elRecordFullName);
|
||||
recordsAPI.completeRecord(rmAdmin.getUsername(), rmAdmin.getPassword(), nonElRecordFullName);
|
||||
|
||||
// edit disposition date
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),CatFolder.getName());
|
||||
|
||||
// cut off the Folder
|
||||
recordFoldersAPI.postFolderAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),CatFolder.getName());
|
||||
|
||||
// Verify the Content
|
||||
Node electronicNode = getNode(elRecord.getId());
|
||||
assertTrue("The content of " + electronicRecord + " is available",
|
||||
StringUtils.isEmpty(electronicNode.getNodeContent().getResponse().getBody().asString()));
|
||||
|
||||
// verify the Properties
|
||||
AssertJUnit.assertNull("The properties are present even after cutting off the record.", elRecord.getProperties().getTitle());
|
||||
|
||||
// delete precondition
|
||||
deleteRecordCategory(Category1.getId());
|
||||
deleteRecordCategory(CopyCategoryId);
|
||||
}
|
||||
/**
|
||||
* Test covering RM-3060
|
||||
* Check the disposition steps for a record can be executed
|
||||
* When the record is linked to a folder with the same disposition schedule
|
||||
* */
|
||||
@Test
|
||||
@AlfrescoTest (jira = "RM-3060")
|
||||
public void sameDispositionScheduleLinkedRecords() throws UnsupportedEncodingException {
|
||||
|
||||
// create a category with retention applied on records level
|
||||
RecordCategory recordCategory = getRestAPIFactory().getFilePlansAPI(rmAdmin)
|
||||
.createRootRecordCategory(RecordCategory.builder().name(firstCategoryRM3060).build(),
|
||||
RecordCategory.DEFAULT_FILE_PLAN_ALIAS);
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(firstCategoryRM3060, true);
|
||||
dispositionScheduleService.addCutOffAfterPeriodStep(firstCategoryRM3060, "week|1", DATE_FILED);
|
||||
dispositionScheduleService.addTransferAfterEventStep(firstCategoryRM3060, TRANSFER_LOCATION, RMEvents.CASE_CLOSED.getEventName());
|
||||
dispositionScheduleService.addDestroyWithoutGhostingAfterPeriodStep(firstCategoryRM3060, "week|1", CUT_OFF_DATE);
|
||||
|
||||
// make a copy of the category created
|
||||
String categorySecondId = copyCategory(getAdminUser(), recordCategory.getId(), secondCategoryRM3060);
|
||||
|
||||
// create a folder on the category firstCategoryRM3060 with a complete electronic record
|
||||
RecordCategoryChild firstFolderRecordCategoryChild = createRecordFolder(recordCategory.getId(),firstFolderRM3060);
|
||||
Record firstElectronicRecord = createElectronicRecord(firstFolderRecordCategoryChild.getId(),electronicRecordRM3060);
|
||||
|
||||
String elRecordFullName = recordsAPI.getRecordFullName(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(),firstFolderRM3060, electronicRecordRM3060);
|
||||
String elRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060);
|
||||
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), elRecordFullName);
|
||||
|
||||
// create a folder on the category secondCategoryRM3060 with a non electronic record
|
||||
RecordCategoryChild secondFolderRecordCategoryChild = createRecordFolder(categorySecondId,secondFolderRM3060);
|
||||
Record secondNonElectronicRecord = createNonElectronicRecord(secondFolderRecordCategoryChild.getId(),nonElectronicRecordRM3060);
|
||||
|
||||
// link the nonElectronicRecordRM3060 to firstFolderRM3060
|
||||
List<String> recordLists = new ArrayList<>();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
String nonElRecordFullName = recordsAPI.getRecordFullName(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), secondFolderRM3060, secondNonElectronicRecord.getName());
|
||||
String nonElRecordNameNodeRef = recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060);
|
||||
|
||||
// complete records and cut them off
|
||||
recordsAPI.completeRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), nonElRecordFullName);
|
||||
|
||||
// edit the disposition date
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
|
||||
// cut off the record
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),nonElRecordNameNodeRef);
|
||||
|
||||
//check the record is cut off
|
||||
AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
|
||||
// link the electronic record to secondFolderRM3060
|
||||
recordLists.clear();
|
||||
recordLists.add(NODE_REF_WORKSPACE_SPACES_STORE + secondNonElectronicRecord.getId());
|
||||
linksAPI.linkRecord(getDataUser().getAdminUser().getUsername(),
|
||||
getDataUser().getAdminUser().getPassword(), HttpStatus.SC_OK,secondCategoryRM3060 + "/" +
|
||||
secondFolderRM3060, recordLists);
|
||||
|
||||
// edit the disposition date and cut off the record
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","cutoff"),elRecordNameNodeRef);
|
||||
|
||||
AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully cut off.", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(CUT_OFF_ASPECT));
|
||||
|
||||
// open the record and complete the disposition schedule event
|
||||
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), elRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
rmRolesAndActionsAPI.completeEvent(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), nonElRecordFullName, RMEvents.CASE_CLOSED, Instant.now());
|
||||
|
||||
// transfer the files & complete transfers
|
||||
HttpResponse nonElRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), nonElRecordFullName, "/" + secondCategoryRM3060 + "/" + secondFolderRM3060));
|
||||
|
||||
String nonElRecordNameTransferId = getTransferId(nonElRecordNameHttpResponse,nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),nonElRecordNameTransferId);
|
||||
|
||||
HttpResponse elRecordNameHttpResponse = recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transfer"),recordsAPI.getRecordNodeRef(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), elRecordFullName, "/" + firstCategoryRM3060 + "/" + firstFolderRM3060));
|
||||
|
||||
String elRecordNameTransferId = getTransferId(elRecordNameHttpResponse,elRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","transferComplete"),elRecordNameTransferId);
|
||||
|
||||
AssertJUnit.assertTrue("The file " + electronicRecordRM3060 + " has not been successfully transferred", getRestAPIFactory().getRecordsAPI().getRecord(firstElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
AssertJUnit.assertTrue("The file " + nonElectronicRecordRM3060 + " has not been successfully transferred.", getRestAPIFactory().getRecordsAPI().getRecord(secondNonElectronicRecord.getId()).getAspectNames().contains(TRANSFER_TYPE));
|
||||
|
||||
// edit the disposition date for nonElectronicRecordRM3060 & electronicRecordRM3060
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),editDispositionDateJson(),elRecordNameNodeRef);
|
||||
|
||||
// destroy nonElectronicRecordRM3060 & electronicRecordRM3060 records
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),nonElRecordNameNodeRef);
|
||||
recordFoldersAPI.postRecordAction(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(),new JSONObject().put("name","destroy"),elRecordNameNodeRef);
|
||||
|
||||
// check the file is not displayed
|
||||
assertNull("The file " + nonElectronicRecordRM3060 + " has not been successfully destroyed.", secondNonElectronicRecord.getContent());
|
||||
assertNull("The file " + electronicRecordRM3060 + " has not been successfully destroyed.", firstElectronicRecord.getContent());
|
||||
|
||||
// delete precondition
|
||||
deleteRecordCategory(recordCategory.getId());
|
||||
deleteRecordCategory(categorySecondId);
|
||||
}
|
||||
private String copyCategory(UserModel user, String categoryId, String copyName) {
|
||||
RepoTestModel repoTestModel = new RepoTestModel() {};
|
||||
repoTestModel.setNodeRef(categoryId);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.7-A5
|
||||
SOLR6_TAG=2.0.7-A2
|
||||
POSTGRES_TAG=14.4
|
||||
ACTIVEMQ_TAG=5.17.4-jre17-rockylinux8
|
||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -436,7 +436,7 @@
|
||||
</run>
|
||||
</image>
|
||||
<image>
|
||||
<name>alfresco/alfresco-activemq:${dependency.activemq.version}-jre17-rockylinux8</name>
|
||||
<name>alfresco/alfresco-activemq:${dependency.activemq.version}-jre11-rockylinux8</name>
|
||||
<run>
|
||||
<ports>
|
||||
<port>${activemq.port1}:${activemq.port1}</port>
|
||||
@@ -507,7 +507,7 @@
|
||||
</run>
|
||||
</image>
|
||||
<image>
|
||||
<name>alfresco/alfresco-activemq:${dependency.activemq.version}-jre17-rockylinux8</name>
|
||||
<name>alfresco/alfresco-activemq:${dependency.activemq.version}-jre11-rockylinux8</name>
|
||||
<run>
|
||||
<ports>
|
||||
<port>${activemq.port1}:${activemq.port1}</port>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#
|
||||
|
||||
# Version label
|
||||
version.major=23
|
||||
version.minor=1
|
||||
version.major=7
|
||||
version.minor=4
|
||||
version.revision=0
|
||||
version.label=
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -38,7 +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':
|
||||
@@ -2092,8 +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
|
||||
@@ -3761,4 +3927,92 @@ definitions:
|
||||
- SiteConsumer
|
||||
- SiteCollaborator
|
||||
- SiteContributor
|
||||
- SiteManager
|
||||
- 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
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -121,6 +121,12 @@
|
||||
<version>${dependency.webscripts.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
||||
@@ -23,10 +23,6 @@ function runAction(p_params)
|
||||
if (p_params.destNode.hasAspect("cm:lockable") && !p_params.destNode.hasAspect("trx:transferred"))
|
||||
{
|
||||
p_params.destNode.unlock();
|
||||
if(p_params.destNode.hasAspect("gd2:editingInGoogle"))
|
||||
{
|
||||
p_params.destNode.removeAspect("gd2:editingInGoogle");
|
||||
}
|
||||
}
|
||||
|
||||
var resultId = originalDoc.name,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -137,10 +137,6 @@
|
||||
<artifactId>commons-dbcp2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.httpclient;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequestInterceptor;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.conn.HttpClientConnectionManager;
|
||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
|
||||
|
||||
public class HttpClient4Factory
|
||||
{
|
||||
protected static final String TLS_PROTOCOL = "TLS";
|
||||
protected static final String HTTPS_PROTOCOL = "https";
|
||||
protected static final String HTTP_TARGET_HOST = "http.target_host";
|
||||
protected static final String TLS_V_1_2 = "TLSv1.2";
|
||||
protected static final String TLS_V_1_3 = "TLSv1.3";
|
||||
|
||||
private static SSLContext createSSLContext(HttpClientConfig config)
|
||||
{
|
||||
KeyManager[] keyManagers = config.getKeyStore().createKeyManagers();
|
||||
TrustManager[] trustManagers = config.getTrustStore().createTrustManagers();
|
||||
|
||||
try
|
||||
{
|
||||
SSLContext sslcontext = SSLContext.getInstance(TLS_PROTOCOL);
|
||||
sslcontext.init(keyManagers, trustManagers, null);
|
||||
return sslcontext;
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to create SSL context", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static CloseableHttpClient createHttpClient(HttpClientConfig config)
|
||||
{
|
||||
return createHttpClient(config, null);
|
||||
}
|
||||
|
||||
public static CloseableHttpClient createHttpClient(HttpClientConfig config, HttpClientConnectionManager connectionManager)
|
||||
{
|
||||
HttpClientBuilder clientBuilder = HttpClients.custom();
|
||||
|
||||
if(config.isMTLSEnabled())
|
||||
{
|
||||
clientBuilder.addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
|
||||
if (!((HttpHost) context.getAttribute(HTTP_TARGET_HOST)).getSchemeName().equals(HTTPS_PROTOCOL))
|
||||
{
|
||||
String msg = "mTLS is enabled but provided URL does not use a secured protocol";
|
||||
throw new HttpClientException(msg);
|
||||
}
|
||||
});
|
||||
clientBuilder.setSSLSocketFactory(getSslConnectionSocketFactory(config));
|
||||
}
|
||||
|
||||
if (connectionManager != null)
|
||||
{
|
||||
clientBuilder.setConnectionManager(connectionManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Setting a connectionManager overrides these properties
|
||||
clientBuilder.setMaxConnTotal(config.getMaxTotalConnections());
|
||||
clientBuilder.setMaxConnPerRoute(config.getMaxHostConnections());
|
||||
}
|
||||
|
||||
RequestConfig requestConfig = RequestConfig.custom()
|
||||
.setConnectTimeout(config.getConnectionTimeout())
|
||||
.setSocketTimeout(config.getSocketTimeout())
|
||||
.setConnectionRequestTimeout(config.getConnectionRequestTimeout())
|
||||
.build();
|
||||
|
||||
clientBuilder.setDefaultRequestConfig(requestConfig);
|
||||
|
||||
clientBuilder.setRetryHandler(new StandardHttpRequestRetryHandler(5, false));
|
||||
|
||||
return clientBuilder.build();
|
||||
}
|
||||
|
||||
private static SSLConnectionSocketFactory getSslConnectionSocketFactory(HttpClientConfig config)
|
||||
{
|
||||
return new SSLConnectionSocketFactory(
|
||||
createSSLContext(config),
|
||||
new String[] { TLS_V_1_2, TLS_V_1_3 },
|
||||
null,
|
||||
config.isHostnameVerificationDisabled() ? new NoopHostnameVerifier() : SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
||||
}
|
||||
|
||||
public static PoolingHttpClientConnectionManager createPoolingConnectionManager(HttpClientConfig config)
|
||||
{
|
||||
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager;
|
||||
if(config.isMTLSEnabled())
|
||||
{
|
||||
poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
|
||||
RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register("https", getSslConnectionSocketFactory(config))
|
||||
.build());
|
||||
}
|
||||
else
|
||||
{
|
||||
poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
|
||||
RegistryBuilder.<ConnectionSocketFactory>create()
|
||||
.register("http", PlainConnectionSocketFactory.getSocketFactory())
|
||||
.build());
|
||||
}
|
||||
poolingHttpClientConnectionManager.setMaxTotal(config.getMaxTotalConnections());
|
||||
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(config.getMaxHostConnections());
|
||||
|
||||
return poolingHttpClientConnectionManager;
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.httpclient;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.encryption.AlfrescoKeyStore;
|
||||
import org.alfresco.encryption.AlfrescoKeyStoreImpl;
|
||||
import org.alfresco.encryption.KeyResourceLoader;
|
||||
import org.alfresco.encryption.ssl.SSLEncryptionParameters;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class HttpClientConfig
|
||||
{
|
||||
private static final String HTTPCLIENT_CONFIG = "httpclient.config.";
|
||||
|
||||
protected static final Log LOGGER = LogFactory.getLog(HttpClientConfig.class);
|
||||
|
||||
private Properties properties;
|
||||
private String serviceName;
|
||||
|
||||
private SSLEncryptionParameters sslEncryptionParameters;
|
||||
private KeyResourceLoader keyResourceLoader;
|
||||
|
||||
private AlfrescoKeyStore keyStore;
|
||||
private AlfrescoKeyStore trustStore;
|
||||
|
||||
private Map<String, String> config;
|
||||
|
||||
public void setProperties(Properties properties)
|
||||
{
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName)
|
||||
{
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public void setSslEncryptionParameters(SSLEncryptionParameters sslEncryptionParameters)
|
||||
{
|
||||
this.sslEncryptionParameters = sslEncryptionParameters;
|
||||
}
|
||||
|
||||
public void setKeyResourceLoader(KeyResourceLoader keyResourceLoader)
|
||||
{
|
||||
this.keyResourceLoader = keyResourceLoader;
|
||||
}
|
||||
|
||||
public AlfrescoKeyStore getKeyStore()
|
||||
{
|
||||
return keyStore;
|
||||
}
|
||||
|
||||
public AlfrescoKeyStore getTrustStore()
|
||||
{
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.keyStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getKeyStoreParameters(), keyResourceLoader);
|
||||
this.trustStore = new AlfrescoKeyStoreImpl(sslEncryptionParameters.getTrustStoreParameters(), keyResourceLoader);
|
||||
|
||||
config = retrieveConfig(serviceName);
|
||||
checkUnsupportedProperties(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used for retrieving HttpClient config from Global Properties
|
||||
* @param serviceName name of used service
|
||||
* @return map of properties
|
||||
*/
|
||||
private Map<String, String> retrieveConfig(String serviceName)
|
||||
{
|
||||
return properties.keySet().stream()
|
||||
.filter(key -> key instanceof String)
|
||||
.map(Object::toString)
|
||||
.filter(key -> key.startsWith(HTTPCLIENT_CONFIG + serviceName))
|
||||
.collect(Collectors.toMap(
|
||||
key -> key.replace(HTTPCLIENT_CONFIG + serviceName + ".", ""),
|
||||
key -> properties.getProperty(key, null)));
|
||||
}
|
||||
|
||||
private void checkUnsupportedProperties(Map<String, String> config)
|
||||
{
|
||||
config.keySet().stream()
|
||||
.filter(propertyName -> !HttpClientPropertiesEnum.isPropertyNameSupported(propertyName))
|
||||
.forEach(propertyName -> LOGGER.warn(String.format("For service [%s], an unsupported property [%s] is set", serviceName, propertyName)));
|
||||
}
|
||||
|
||||
private Integer getIntegerProperty(HttpClientPropertiesEnum property)
|
||||
{
|
||||
return Integer.parseInt(extractValueFromConfig(property).orElse("0"));
|
||||
}
|
||||
|
||||
private Boolean getBooleanProperty(HttpClientPropertiesEnum property)
|
||||
{
|
||||
return Boolean.parseBoolean(extractValueFromConfig(property).orElse("false"));
|
||||
}
|
||||
|
||||
private Optional<String> extractValueFromConfig(HttpClientPropertiesEnum property)
|
||||
{
|
||||
Optional<String> optionalProperty = Optional.ofNullable(config.get(property.name));
|
||||
if(property.isRequired && optionalProperty.isEmpty())
|
||||
{
|
||||
String msg = String.format("Required property: '%s' is empty.", property.name);
|
||||
throw new HttpClientException(msg);
|
||||
}
|
||||
return optionalProperty;
|
||||
}
|
||||
|
||||
public Integer getConnectionTimeout()
|
||||
{
|
||||
return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT);
|
||||
}
|
||||
|
||||
public Integer getSocketTimeout()
|
||||
{
|
||||
return getIntegerProperty(HttpClientPropertiesEnum.SOCKET_TIMEOUT);
|
||||
}
|
||||
|
||||
public Integer getConnectionRequestTimeout()
|
||||
{
|
||||
return getIntegerProperty(HttpClientPropertiesEnum.CONNECTION_REQUEST_TIMEOUT);
|
||||
}
|
||||
|
||||
public Integer getMaxTotalConnections()
|
||||
{
|
||||
return getIntegerProperty(HttpClientPropertiesEnum.MAX_TOTAL_CONNECTIONS);
|
||||
}
|
||||
|
||||
public Integer getMaxHostConnections()
|
||||
{
|
||||
return getIntegerProperty(HttpClientPropertiesEnum.MAX_HOST_CONNECTIONS);
|
||||
}
|
||||
|
||||
public Boolean isMTLSEnabled()
|
||||
{
|
||||
return getBooleanProperty(HttpClientPropertiesEnum.MTLS_ENABLED);
|
||||
}
|
||||
|
||||
public boolean isHostnameVerificationDisabled()
|
||||
{
|
||||
return getBooleanProperty(HttpClientPropertiesEnum.HOSTNAME_VERIFICATION_DISABLED);
|
||||
}
|
||||
|
||||
private enum HttpClientPropertiesEnum
|
||||
{
|
||||
CONNECTION_TIMEOUT("connectionTimeout", true),
|
||||
SOCKET_TIMEOUT("socketTimeout", true),
|
||||
CONNECTION_REQUEST_TIMEOUT("connectionRequestTimeout", true),
|
||||
MAX_TOTAL_CONNECTIONS("maxTotalConnections", true),
|
||||
MAX_HOST_CONNECTIONS("maxHostConnections", true),
|
||||
HOSTNAME_VERIFICATION_DISABLED("hostnameVerificationDisabled", false),
|
||||
MTLS_ENABLED("mTLSEnabled", true);
|
||||
|
||||
private final String name;
|
||||
private final Boolean isRequired;
|
||||
|
||||
HttpClientPropertiesEnum(String propertyName, Boolean isRequired)
|
||||
{
|
||||
this.name = propertyName;
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
|
||||
private static final List<String> supportedProperties = new ArrayList<>();
|
||||
|
||||
static {
|
||||
for (HttpClientPropertiesEnum property : HttpClientPropertiesEnum.values()) {
|
||||
supportedProperties.add(property.name);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPropertyNameSupported(String propertyName) {
|
||||
return supportedProperties.contains(propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.httpclient;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
|
||||
public class HttpClientException extends AlfrescoRuntimeException
|
||||
{
|
||||
public HttpClientException(String msgId)
|
||||
{
|
||||
super(msgId);
|
||||
}
|
||||
}
|
||||
@@ -45,13 +45,6 @@ public class ListBackedPagingResults<R> implements PagingResults<R>
|
||||
size = list.size();
|
||||
hasMore = false;
|
||||
}
|
||||
|
||||
public ListBackedPagingResults(List<R> list, boolean hasMore)
|
||||
{
|
||||
this(list);
|
||||
this.hasMore = hasMore;
|
||||
}
|
||||
|
||||
public ListBackedPagingResults(List<R> list, PagingRequest paging)
|
||||
{
|
||||
// Excerpt
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -119,7 +119,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jibx</groupId>
|
||||
<artifactId>jibx-run</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -134,7 +134,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.woodstox</groupId>
|
||||
<artifactId>woodstox-core</artifactId>
|
||||
<version>6.5.1</version>
|
||||
<version>6.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- the cxf libs were updated, see dependencyManagement section -->
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.7-A5
|
||||
SOLR6_TAG=2.0.7-A2
|
||||
POSTGRES_TAG=14.4
|
||||
ACTIVEMQ_TAG=5.17.4-jre17-rockylinux8
|
||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
@@ -16,12 +16,12 @@
|
||||
</organization>
|
||||
|
||||
<properties>
|
||||
<maven.build.sourceVersion>17</maven.build.sourceVersion>
|
||||
<maven.build.sourceVersion>11</maven.build.sourceVersion>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<chemistry-opencmis-commons-api>1.1.0</chemistry-opencmis-commons-api>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<maven-release.version>2.5.3</maven-release.version>
|
||||
<java.version>17</java.version>
|
||||
<java.version>11</java.version>
|
||||
<suiteXmlFile>${project.basedir}/src/test/resources/cmis-suite.xml</suiteXmlFile>
|
||||
<cmis.binding />
|
||||
<cmis.basePath />
|
||||
@@ -58,6 +58,12 @@
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jackson2-provider</artifactId>
|
||||
<version>4.7.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- alfresco tester settings -->
|
||||
<dependency>
|
||||
<groupId>org.alfresco.tas</groupId>
|
||||
|
||||
@@ -4,6 +4,8 @@ import org.alfresco.utility.data.AisToken;
|
||||
import org.alfresco.utility.data.auth.DataAIS;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.chemistry.opencmis.commons.SessionParameter;
|
||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -84,9 +86,9 @@ public class AuthParameterProviderFactory
|
||||
parameters.put(SessionParameter.OAUTH_REFRESH_TOKEN, aisToken.getRefreshToken());
|
||||
parameters.put(SessionParameter.OAUTH_EXPIRATION_TIMESTAMP, String.valueOf(System.currentTimeMillis()
|
||||
+ (aisToken.getExpiresIn() * 1000))); // getExpiresIn is in seconds
|
||||
parameters.put(SessionParameter.OAUTH_TOKEN_ENDPOINT, cmisProperties.aisProperty().getAuthServerUrl()
|
||||
parameters.put(SessionParameter.OAUTH_TOKEN_ENDPOINT, cmisProperties.aisProperty().getAdapterConfig().getAuthServerUrl()
|
||||
+ "/realms/alfresco/protocol/openid-connect/token");
|
||||
parameters.put(SessionParameter.OAUTH_CLIENT_ID, cmisProperties.aisProperty().getResource());
|
||||
parameters.put(SessionParameter.OAUTH_CLIENT_ID, cmisProperties.aisProperty().getAdapterConfig().getResource());
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@@ -108,10 +110,10 @@ public class AuthParameterProviderFactory
|
||||
// Attempt to get an access token for userModel from AIS
|
||||
aisToken = dataAIS.perform().getAccessToken(userModel);
|
||||
}
|
||||
catch (AssertionError e)
|
||||
catch (HttpResponseException e)
|
||||
{
|
||||
// Trying to authenticate with invalid user credentials so return an invalid access token
|
||||
if (e.getMessage().contains("invalid_grant"))
|
||||
if (e.getStatusCode() == 401)
|
||||
{
|
||||
STEP(String.format("%s Invalid user credentials were provided %s:%s. Using invalid token for reqest.",
|
||||
STEP_PREFIX, userModel.getUsername(), userModel.getPassword()));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
@@ -95,6 +95,7 @@
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>${dependency.jakarta-json-path.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -8,19 +8,20 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<suiteXmlFile>${project.basedir}/src/test/resources/restapi-suite.xml</suiteXmlFile>
|
||||
<maven.build.sourceVersion>17</maven.build.sourceVersion>
|
||||
<maven.build.sourceVersion>11</maven.build.sourceVersion>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<rest.api.explorer.branch>master</rest.api.explorer.branch>
|
||||
<httpclient-osgi-version>4.5.6</httpclient-osgi-version>
|
||||
<org.glassfish.version>1.1.4</org.glassfish.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<scribejava-apis.version>8.3.3</scribejava-apis.version>
|
||||
<java.version>17</java.version>
|
||||
<scribejava-apis.version>8.3.1</scribejava-apis.version>
|
||||
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
@@ -84,13 +85,6 @@
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>${dependency.awaitility.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- REST ASSURED -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
@@ -171,14 +165,14 @@
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<version>3.0.17</version>
|
||||
<version>3.0.12</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-json-->
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-json</artifactId>
|
||||
<version>3.0.17</version>
|
||||
<version>3.0.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -30,6 +30,7 @@ import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import org.alfresco.utility.data.AisToken;
|
||||
import org.alfresco.utility.data.auth.DataAIS;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.keycloak.authorization.client.util.HttpResponseException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -85,11 +86,12 @@ public class RestAisAuthentication
|
||||
// Attempt to get an access token for userModel from AIS
|
||||
aisToken = dataAIS.perform().getAccessToken(userModel);
|
||||
}
|
||||
catch (AssertionError e)
|
||||
catch (HttpResponseException e)
|
||||
{
|
||||
// Trying to authenticate with invalid user credentials or disabled
|
||||
// user so return an invalid access token
|
||||
if (e.getMessage().contains("invalid_grant"))
|
||||
String httpResponse = new String(e.getBytes());
|
||||
if (e.getStatusCode() == 401 || httpResponse.contains(USER_DISABLED_MSG))
|
||||
{
|
||||
STEP(String.format("%s User disabled or invalid user credentials were provided %s:%s. Using invalid token for request.", STEP_PREFIX,
|
||||
userModel.getUsername(), userModel.getPassword()));
|
||||
|
||||
@@ -680,22 +680,17 @@ public class RestWrapper extends DSLWrapper<RestWrapper>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (returnedResponse.asString().isEmpty())
|
||||
{
|
||||
LOG.info("On {} {}, received the following response \n{}", restRequest.getHttpMethod(), restRequest.getPath(),
|
||||
returnedResponse.getStatusCode());
|
||||
}
|
||||
else if (returnedResponse.getContentType().contains("image/png"))
|
||||
if (returnedResponse.getContentType().contains("image/png"))
|
||||
{
|
||||
LOG.info("On {} {}, received the response with an image and headers: \n{}", restRequest.getHttpMethod(), restRequest.getPath(),
|
||||
returnedResponse.getHeaders().toString());
|
||||
returnedResponse.getHeaders().toString());
|
||||
}
|
||||
else if (returnedResponse.getContentType().contains("application/json"))
|
||||
else if (returnedResponse.getContentType().contains("application/json") && !returnedResponse.asString().isEmpty())
|
||||
{
|
||||
LOG.info("On {} {}, received the following response \n{}", restRequest.getHttpMethod(), restRequest.getPath(),
|
||||
Utility.prettyPrintJsonString(returnedResponse.asString()));
|
||||
Utility.prettyPrintJsonString(returnedResponse.asString()));
|
||||
}
|
||||
else if (returnedResponse.getContentType().contains("application/xml"))
|
||||
else if (returnedResponse.getContentType().contains("application/xml") && !returnedResponse.asString().isEmpty())
|
||||
{
|
||||
String response = parseXML(returnedResponse);
|
||||
LOG.info("On {} {}, received the following response \n{}", restRequest.getHttpMethod(), restRequest.getPath(), response);
|
||||
@@ -703,7 +698,7 @@ public class RestWrapper extends DSLWrapper<RestWrapper>
|
||||
else
|
||||
{
|
||||
LOG.info("On {} {}, received the following response \n{}", restRequest.getHttpMethod(), restRequest.getPath(),
|
||||
ToStringBuilder.reflectionToString(returnedResponse.asString(), ToStringStyle.MULTI_LINE_STYLE));
|
||||
ToStringBuilder.reflectionToString(returnedResponse.asString(), ToStringStyle.MULTI_LINE_STYLE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.rest.core.IRestModelsCollection;
|
||||
import org.alfresco.utility.exception.TestConfigurationException;
|
||||
@@ -120,7 +117,7 @@ public class ModelsCollectionAssertion<C>
|
||||
return (C) modelCollection;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings("unchecked")
|
||||
public C entriesListDoesNotContain(String key, String value)
|
||||
{
|
||||
boolean exist = false;
|
||||
@@ -146,53 +143,6 @@ public class ModelsCollectionAssertion<C>
|
||||
return (C) modelCollection;
|
||||
}
|
||||
|
||||
public C entrySetContains(String key, String... expectedValues)
|
||||
{
|
||||
return entrySetContains(key, Arrays.stream(expectedValues).collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public C entrySetContains(String key, Collection<String> expectedValues)
|
||||
{
|
||||
Collection<String> actualValues = ((List<Model>) modelCollection.getEntries()).stream()
|
||||
.map(model -> extractValueAsString(model, key))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Assert.assertTrue(actualValues.containsAll(expectedValues), String.format("Entry with key: \"%s\" is expected to contain values: %s, but actual values are: %s",
|
||||
key, expectedValues, actualValues));
|
||||
|
||||
return (C) modelCollection;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public C entrySetMatches(String key, Collection<String> expectedValues)
|
||||
{
|
||||
Collection<String> actualValues = ((List<Model>) modelCollection.getEntries()).stream()
|
||||
.map(model -> extractValueAsString(model, key))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Assert.assertEqualsNoOrder(actualValues, expectedValues, String.format("Entry with key: \"%s\" is expected to match values: %s, but actual values are: %s",
|
||||
key, expectedValues, actualValues));
|
||||
|
||||
return (C) modelCollection;
|
||||
}
|
||||
|
||||
private String extractValueAsString(Model model, String key)
|
||||
{
|
||||
String fieldValue;
|
||||
Object modelObject = loadModel(model);
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String jsonInString = mapper.writeValueAsString(modelObject);
|
||||
fieldValue = JsonPath.with(jsonInString).get(key);
|
||||
} catch (Exception e) {
|
||||
throw new TestConfigurationException(String.format(
|
||||
"You try to assert field [%s] that doesn't exist in class: [%s]. Exception: %s, Please check your code!",
|
||||
key, getClass().getCanonicalName(), e.getMessage()));
|
||||
}
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public C entriesListDoesNotContain(String key)
|
||||
{
|
||||
|
||||
@@ -52,11 +52,6 @@ This must be unique within the parent category.
|
||||
*/
|
||||
private long count;
|
||||
|
||||
/**
|
||||
The path to this category.
|
||||
*/
|
||||
private String path;
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return this.id;
|
||||
@@ -107,14 +102,6 @@ This must be unique within the parent category.
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
@@ -139,7 +126,6 @@ This must be unique within the parent category.
|
||||
", parentId='" + parentId + '\'' +
|
||||
", hasChildren=" + hasChildren +
|
||||
", count=" + count +
|
||||
", path=" + path +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public class RestErrorModel
|
||||
public static String INVALID_MAXITEMS = "Invalid paging parameter maxItems:%s";
|
||||
public static String INVALID_SKIPCOUNT = "Invalid paging parameter skipCount:%s";
|
||||
public static String INVALID_TAG = "Tag name must not contain %s char sequence";
|
||||
public static String BLANK_TAG = "New tag cannot be blank";
|
||||
public static String EMPTY_TAG = "New tag cannot be null";
|
||||
public static String UNKNOWN_ROLE = "Unknown role '%s'";
|
||||
public static String ALREADY_Site_MEMBER = "%s is already a member of site %s";
|
||||
public static String ALREADY_INVITED = "%s is already invited to site %s";
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 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.categories;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.model.RestCategoryLinkBodyModel;
|
||||
import org.alfresco.rest.model.RestCategoryModel;
|
||||
import org.alfresco.rest.model.RestCategoryModelsCollection;
|
||||
import org.alfresco.utility.Utility;
|
||||
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.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class CategoriesPathTests extends CategoriesRestTest
|
||||
{
|
||||
private FileModel file;
|
||||
private RestCategoryModel category;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
@Override
|
||||
public void dataPreparation() throws Exception
|
||||
{
|
||||
STEP("Create user and site");
|
||||
user = dataUser.createRandomTestUser();
|
||||
SiteModel site = dataSite.usingUser(user).createPublicRandomSite();
|
||||
|
||||
STEP("Create a folder, file in it and a category");
|
||||
FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
|
||||
file = dataContent.usingUser(user).usingResource(folder).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
category = prepareCategoryUnderRoot();
|
||||
|
||||
STEP("Wait for indexing to complete");
|
||||
Utility.sleep(1000, 60000, () -> restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(category)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.getCategory()
|
||||
.assertThat()
|
||||
.field(FIELD_PATH)
|
||||
.isNotNull());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify path for a category got by ID.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetCategoryById_includePath()
|
||||
{
|
||||
STEP("Get category and verify if path is a general path for categories");
|
||||
final RestCategoryModel actualCategory = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(category)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.getCategory();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
actualCategory.assertThat().field(FIELD_ID).is(category.getId());
|
||||
actualCategory.assertThat().field(FIELD_PATH).is("/categories/General");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify path for category.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetCategories_includePath()
|
||||
{
|
||||
STEP("Get few categories and verify its paths");
|
||||
final RestCategoryModel parentCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModelsCollection actualCategories = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(parentCategory)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.getCategoryChildren();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
assertTrue(actualCategories.getEntries().stream()
|
||||
.map(RestCategoryModel::onModel)
|
||||
.allMatch(cat -> cat.getPath().equals("/categories/General")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify path for child category.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testGetChildCategory_includePath()
|
||||
{
|
||||
STEP("Create parent and child categories");
|
||||
final RestCategoryModel parentCategory = prepareCategoryUnderRoot();
|
||||
final RestCategoryModel childCategory = prepareCategoryUnder(parentCategory);
|
||||
|
||||
STEP("Verify path for created child categories");
|
||||
final RestCategoryModelsCollection actualCategories = restClient.authenticateUser(user)
|
||||
.withCoreAPI()
|
||||
.usingCategory(parentCategory)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.getCategoryChildren();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
actualCategories.getEntries().stream()
|
||||
.map(RestCategoryModel::onModel)
|
||||
.forEach(cat -> cat.assertThat().field(FIELD_PATH).is("/categories/General/" + parentCategory.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create category and verify that it has a path.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testCreateCategory_includingPath()
|
||||
{
|
||||
STEP("Create a category under root and verify if path is a general path for categories");
|
||||
final String categoryName = getRandomName("Category");
|
||||
final RestCategoryModel rootCategory = createCategoryModelWithId(ROOT_CATEGORY_ID);
|
||||
final RestCategoryModel aCategory = createCategoryModelWithName(categoryName);
|
||||
final RestCategoryModel createdCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.usingCategory(rootCategory)
|
||||
.createSingleCategory(aCategory);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
createdCategory.assertThat().field(FIELD_NAME).is(categoryName);
|
||||
createdCategory.assertThat().field(FIELD_PATH).is("/categories/General");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update category and verify that it has a path.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testUpdateCategory_includePath()
|
||||
{
|
||||
STEP("Update linked category and verify if path is a general path for categories");
|
||||
final String categoryNewName = getRandomName("NewCategoryName");
|
||||
final RestCategoryModel fixedCategoryModel = createCategoryModelWithName(categoryNewName);
|
||||
final RestCategoryModel updatedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingCategory(category)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.updateCategory(fixedCategoryModel);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
updatedCategory.assertThat().field(FIELD_ID).is(category.getId());
|
||||
updatedCategory.assertThat().field(FIELD_PATH).is("/categories/General");
|
||||
}
|
||||
|
||||
/**
|
||||
* Link node to categories and verify that they have path.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testLinkNodeToCategories_includePath()
|
||||
{
|
||||
STEP("Link node to categories and verify if path is a general path");
|
||||
final RestCategoryLinkBodyModel categoryLinkModel = createCategoryLinkModelWithId(category.getId());
|
||||
final RestCategoryModel linkedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingNode(file)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.linkToCategory(categoryLinkModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
linkedCategory.assertThat().field(FIELD_ID).is(category.getId());
|
||||
linkedCategory.assertThat().field(FIELD_PATH).is("/categories/General");
|
||||
}
|
||||
|
||||
/**
|
||||
* List categories for given node and verify that they have a path.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API })
|
||||
public void testListCategoriesForNode_includePath()
|
||||
{
|
||||
STEP("Link file to category");
|
||||
final RestCategoryLinkBodyModel categoryLink = createCategoryLinkModelWithId(category.getId());
|
||||
final RestCategoryModel linkedCategory = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingNode(file)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.linkToCategory(categoryLink);
|
||||
|
||||
STEP("Get linked category and verify if path is a general path");
|
||||
final RestCategoryModelsCollection linkedCategories = restClient.authenticateUser(dataUser.getAdminUser())
|
||||
.withCoreAPI()
|
||||
.usingNode(file)
|
||||
.include(INCLUDE_PATH_PARAM)
|
||||
.getLinkedCategories();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
linkedCategories.assertThat().entriesListCountIs(1);
|
||||
linkedCategories.getEntries().get(0).onModel().assertThat().field(FIELD_ID).is(category.getId());
|
||||
linkedCategories.getEntries().get(0).onModel().assertThat().field(FIELD_PATH).is("/categories/General");
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,6 @@ import org.testng.annotations.BeforeClass;
|
||||
abstract class CategoriesRestTest extends RestTest
|
||||
{
|
||||
protected static final String INCLUDE_COUNT_PARAM = "count";
|
||||
protected static final String INCLUDE_PATH_PARAM = "path";
|
||||
protected static final String ROOT_CATEGORY_ID = "-root-";
|
||||
protected static final String CATEGORY_NAME_PREFIX = "CategoryName";
|
||||
protected static final String FIELD_NAME = "name";
|
||||
@@ -54,7 +53,6 @@ abstract class CategoriesRestTest extends RestTest
|
||||
protected static final String FIELD_PARENT_ID = "parentId";
|
||||
protected static final String FIELD_HAS_CHILDREN = "hasChildren";
|
||||
protected static final String FIELD_COUNT = "count";
|
||||
protected static final String FIELD_PATH = "path";
|
||||
|
||||
protected UserModel user;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.alfresco.rest.renditions;
|
||||
|
||||
import java.time.Duration;
|
||||
import com.google.common.base.Predicates;
|
||||
import org.alfresco.rest.RestTest;
|
||||
import org.alfresco.rest.core.RestResponse;
|
||||
import org.alfresco.rest.model.RestNodeModel;
|
||||
@@ -10,8 +8,6 @@ import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Durations;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
@@ -72,23 +68,15 @@ public abstract class RenditionIntegrationTests extends RestTest
|
||||
*/
|
||||
protected RestNodeModel uploadFile(String sourceFile) throws Exception
|
||||
{
|
||||
FolderModel folder = Awaitility
|
||||
.await()
|
||||
.atMost(Duration.ofSeconds(30))
|
||||
.pollInterval(Durations.ONE_SECOND)
|
||||
.ignoreExceptions()
|
||||
.until(() -> {
|
||||
FolderModel randomFolderModel = FolderModel.getRandomFolderModel();
|
||||
return dataContent.usingUser(user).usingSite(site).createFolder(randomFolderModel);
|
||||
}, Predicates.notNull());
|
||||
FolderModel folder = FolderModel.getRandomFolderModel();
|
||||
folder = dataContent.usingUser(user).usingSite(site).createFolder(folder);
|
||||
restClient.authenticateUser(user).configureRequestSpec()
|
||||
.addMultiPart("filedata", Utility.getResourceTestDataFile(sourceFile));
|
||||
.addMultiPart("filedata", Utility.getResourceTestDataFile(sourceFile));
|
||||
RestNodeModel fileNode = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createNode();
|
||||
|
||||
Assert.assertEquals(Integer.valueOf(restClient.getStatusCode()).intValue(), HttpStatus.CREATED.value(),
|
||||
"Failed to created a node for rendition tests using file " + sourceFile);
|
||||
"Failed to created a node for rendition tests using file " + sourceFile);
|
||||
|
||||
return fileNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import org.alfresco.rest.model.RestErrorModel;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
@@ -19,14 +14,9 @@ import org.testng.annotations.Test;
|
||||
public class GetTagTests extends TagsDataPrep
|
||||
{
|
||||
|
||||
private static final String FIELD_ID = "id";
|
||||
private static final String FIELD_TAG = "tag";
|
||||
private static final String FIELD_COUNT = "count";
|
||||
private static final String TAG_NAME_PREFIX = "tag-name";
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify admin user gets tag using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsAbleToGetTag()
|
||||
public void adminIsAbleToGetTag() throws Exception
|
||||
{
|
||||
RestTagModel returnedTag = restClient.authenticateUser(adminUserModel).withCoreAPI().getTag(documentTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
@@ -35,7 +25,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify user with Manager role gets tag using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void userWithManagerRoleIsAbleToGetTag()
|
||||
public void userWithManagerRoleIsAbleToGetTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
|
||||
@@ -47,7 +37,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Collaborator role gets tag using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void userWithCollaboratorRoleIsAbleToGetTag()
|
||||
public void userWithCollaboratorRoleIsAbleToGetTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag);
|
||||
@@ -57,7 +47,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Contributor role gets tag using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void userWithContributorRoleIsAbleToGetTag()
|
||||
public void userWithContributorRoleIsAbleToGetTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor));
|
||||
RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag);
|
||||
@@ -67,7 +57,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Consumer role gets tag using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void userWithConsumerRoleIsAbleToGetTag()
|
||||
public void userWithConsumerRoleIsAbleToGetTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag);
|
||||
@@ -78,7 +68,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify Manager user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void managerIsNotAbleToGetTagIfAuthenticationFails()
|
||||
public void managerIsNotAbleToGetTagIfAuthenticationFails() throws Exception
|
||||
{
|
||||
UserModel managerUser = dataUser.usingAdmin().createRandomTestUser();
|
||||
String managerPassword = managerUser.getPassword();
|
||||
@@ -92,7 +82,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if tag id is invalid status code returned is 400")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void invalidTagIdTest()
|
||||
public void invalidTagIdTest() throws Exception
|
||||
{
|
||||
String tagId = documentTag.getId();
|
||||
documentTag.setId("random_tag_value");
|
||||
@@ -104,7 +94,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Check that properties filter is applied when getting tag using Manager user.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void checkPropertiesFilterIsApplied()
|
||||
public void checkPropertiesFilterIsApplied() throws Exception
|
||||
{
|
||||
RestTagModel returnedTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withParams("properties=id,tag").withCoreAPI().getTag(documentTag);
|
||||
@@ -117,7 +107,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Check that Manager user can get tag of a folder.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void getTagOfAFolder()
|
||||
public void getTagOfAFolder() throws Exception
|
||||
{
|
||||
RestTagModel returnedTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withCoreAPI().getTag(folderTag);
|
||||
@@ -128,7 +118,7 @@ public class GetTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Check default error model schema. Use invalid skipCount parameter.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void checkDefaultErrorModelSchema()
|
||||
public void checkDefaultErrorModelSchema() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withParams("skipCount=abc").withCoreAPI().getTag(documentTag);
|
||||
@@ -138,44 +128,4 @@ public class GetTagTests extends TagsDataPrep
|
||||
.descriptionURLIs(RestErrorModel.RESTAPIEXPLORER)
|
||||
.stackTraceIs(RestErrorModel.STACKTRACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that count field is not present for searched tag when not requested.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void testGetTag_notIncludingCount()
|
||||
{
|
||||
STEP("Create single tag as admin");
|
||||
String tagName = getRandomName(TAG_NAME_PREFIX).toLowerCase();
|
||||
final RestTagModel tagModel = createTagModelWithName(tagName);
|
||||
final RestTagModel createdTag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(tagModel);
|
||||
|
||||
restClient.assertStatusCodeIs(CREATED);
|
||||
|
||||
STEP("Get a single tag, not including count and verify if it is not present in the response");
|
||||
final RestTagModel searchedTag = restClient.withCoreAPI().getTag(createdTag);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
RestTagModel expected = RestTagModel.builder().id(createdTag.getId()).tag(tagName).create();
|
||||
searchedTag.assertThat().isEqualTo(expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the count field can be included.
|
||||
*/
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTag_includeCount()
|
||||
{
|
||||
STEP("Create unused tag as admin");
|
||||
String tagName = getRandomName(TAG_NAME_PREFIX).toLowerCase();
|
||||
RestTagModel tagModel = createTagModelWithName(tagName);
|
||||
RestTagModel createdTag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(tagModel);
|
||||
|
||||
STEP("Get a single tag with the count field");
|
||||
RestTagModel searchedTag = restClient.withCoreAPI().include("count").getTag(createdTag);
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
RestTagModel expected = RestTagModel.builder().id(createdTag.getId()).tag(tagName).count(0).create();
|
||||
searchedTag.assertThat().isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,219 +1,79 @@
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.rest.model.RestErrorModel;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
import org.alfresco.rest.model.RestTagModelsCollection;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.data.RandomData;
|
||||
import org.alfresco.utility.model.TestGroup;
|
||||
import org.alfresco.utility.testrail.ExecutionType;
|
||||
import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
|
||||
@Test(groups = {TestGroup.REQUIRE_SOLR})
|
||||
public class GetTagsTests extends TagsDataPrep
|
||||
{
|
||||
|
||||
private static final String FIELD_ID = "id";
|
||||
private static final String FIELD_TAG = "tag";
|
||||
private static final String FIELD_COUNT = "count";
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void dataPreparation() throws Exception
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify user with Manager role gets tags using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void getTagsWithManagerRole()
|
||||
public void getTagsWithManagerRole() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Collaborator role gets tags using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void getTagsWithCollaboratorRole()
|
||||
public void getTagsWithCollaboratorRole() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Contributor role gets tags using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void getTagsWithContributorRole()
|
||||
public void getTagsWithContributorRole() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor));
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Consumer role gets tags using REST API and status code is OK (200)")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void getTagsWithConsumerRole()
|
||||
public void getTagsWithConsumerRole() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Include count in the query parameters and ensure count is as expected for returned tags.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withIncludeCount()
|
||||
{
|
||||
STEP("Get tags including count filter and ensure count is as expected for returned tags");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
|
||||
returnedCollection.getEntries().stream()
|
||||
.filter(e -> e.onModel().getTag().equals(folderTagValue) || e.onModel().getTag().equals(documentTagValue))
|
||||
.forEach(e -> e.onModel().assertThat().field("count").is(2));
|
||||
|
||||
returnedCollection.getEntries().stream()
|
||||
.filter(e -> e.onModel().getTag().equals(documentTagValue2))
|
||||
.forEach(e -> e.onModel().assertThat().field("count").is(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count. Default sort order should be ascending
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountDefaultOrderShouldBeAsc()
|
||||
{
|
||||
STEP("Get tags and order results by count. Default sort order should be ascending");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count in ascending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountAsc()
|
||||
{
|
||||
STEP("Get tags and order results by count in ascending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count ASC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count in descending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountDesc()
|
||||
{
|
||||
STEP("Get tags and order results by count in descending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count DESC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedDescBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name. Default sort order should be ascending
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagDefaultOrderShouldBeAsc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name. Default sort order should be ascending");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name in ascending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagAsc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name in ascending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag ASC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name in descending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagDesc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name in descending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag DESC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedDescBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that we get a 400 error when we request to order by count without also including the tag count.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_orderByCountWithoutIncludeCount()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Failed authentication get tags call returns status code 401 with Manager role")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void failedAuthenticationReturnsUnauthorizedStatus()
|
||||
public void failedAuthenticationReturnsUnauthorizedStatus() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
userModel = dataUser.createRandomTestUser();
|
||||
@@ -227,7 +87,7 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if maxItems is invalid status code returned is 400")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void maxItemsInvalidValueTest()
|
||||
public void maxItemsInvalidValueTest() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withParams("maxItems=abc").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST).assertLastError().containsSummary(String.format(RestErrorModel.INVALID_MAXITEMS, "abc"));
|
||||
@@ -236,7 +96,7 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if skipCount is invalid status code returned is 400")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void skipCountInvalidValueTest()
|
||||
public void skipCountInvalidValueTest() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel).withParams("skipCount=abc").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST).assertLastError().containsSummary(String.format(RestErrorModel.INVALID_SKIPCOUNT, "abc"));
|
||||
@@ -245,55 +105,55 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that file tag is retrieved")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void fileTagIsRetrieved()
|
||||
public void fileTagIsRetrieved() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that folder tag is retrieved")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void folderTagIsRetrieved()
|
||||
public void folderTagIsRetrieved() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", folderTagValue);
|
||||
.and().entriesListContains("tag", folderTagValue.toLowerCase());
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify site Manager is able to get tags using properties parameter."
|
||||
+ "Check that properties filter is applied.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void siteManagerIsAbleToRetrieveTagsWithPropertiesParameter()
|
||||
public void siteManagerIsAbleToRetrieveTagsWithPropertiesParameter() throws Exception
|
||||
{
|
||||
returnedCollection = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withParams("maxItems=5000&properties=tag").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2)
|
||||
.and().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase())
|
||||
.and().entriesListDoesNotContain("id");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "With admin get tags and use skipCount parameter. Check pagination")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void useSkipCountCheckPagination()
|
||||
public void useSkipCountCheckPagination() throws Exception
|
||||
{
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel).withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
RestTagModel firstTag = returnedCollection.getEntries().get(0).onModel();
|
||||
RestTagModel secondTag = returnedCollection.getEntries().get(1).onModel();
|
||||
RestTagModelsCollection tagsWithSkipCount = restClient.withParams("skipCount=2").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
tagsWithSkipCount.assertThat().entriesListDoesNotContain("tag", firstTag.getTag())
|
||||
.assertThat().entriesListDoesNotContain("tag", secondTag.getTag());
|
||||
@@ -303,15 +163,15 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "With admin get tags and use maxItems parameter. Check pagination")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void useMaxItemsParameterCheckPagination()
|
||||
public void useMaxItemsParameterCheckPagination() throws Exception
|
||||
{
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel).withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
RestTagModel firstTag = returnedCollection.getEntries().get(0).onModel();
|
||||
RestTagModel secondTag = returnedCollection.getEntries().get(1).onModel();
|
||||
RestTagModelsCollection tagsWithMaxItems = restClient.withParams("maxItems=2").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
|
||||
tagsWithMaxItems.assertThat().entriesListContains("tag", firstTag.getTag())
|
||||
.assertThat().entriesListContains("tag", secondTag.getTag())
|
||||
@@ -322,22 +182,23 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "With manager get tags and use high skipCount parameter. Check pagination")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void useHighSkipCountCheckPagination()
|
||||
public void useHighSkipCountCheckPagination() throws Exception
|
||||
{
|
||||
returnedCollection = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withParams("skipCount=20000").withCoreAPI().getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat().entriesListIsEmpty()
|
||||
.getPagination().assertThat().field("maxItems").is(100)
|
||||
.and().field("hasMoreItems").is("false")
|
||||
.and().field("count").is("0")
|
||||
.and().field("skipCount").is(20000);
|
||||
.and().field("skipCount").is(20000)
|
||||
.and().field("totalItems").isNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "With Collaborator user get tags and use maxItems with value zero. Check default error model schema")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void useMaxItemsWithValueZeroCheckDefaultErrorModelSchema()
|
||||
public void useMaxItemsWithValueZeroCheckDefaultErrorModelSchema() throws Exception
|
||||
{
|
||||
returnedCollection = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator))
|
||||
.withParams("maxItems=0").withCoreAPI().getTags();
|
||||
@@ -351,167 +212,18 @@ public class GetTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "With Manager user delete tag. Check it is not retrieved anymore.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void checkThatDeletedTagIsNotRetrievedAnymore()
|
||||
public void checkThatDeletedTagIsNotRetrievedAnymore() throws Exception
|
||||
{
|
||||
String removedTag = getRandomName("tag3");
|
||||
String removedTag = RandomData.getRandomName("tag3");
|
||||
|
||||
RestTagModel deletedTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withCoreAPI().usingResource(document).addTag(removedTag);
|
||||
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingTag(deletedTag).deleteTag();
|
||||
restClient.withCoreAPI().usingResource(document).deleteTag(deletedTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT);
|
||||
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
returnedCollection.assertThat().entriesListIsNotEmpty()
|
||||
.and().entriesListDoesNotContain("tag", removedTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if exact name filter can be applied.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withSingleNameFilter()
|
||||
{
|
||||
STEP("Get tags with names filter using EQUALS and expect one item in result");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(tag='" + documentTag.getTag() + "')")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat()
|
||||
.entrySetMatches("tag", Set.of(documentTagValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if multiple names can be applied as a filter.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withTwoNameFilters()
|
||||
{
|
||||
STEP("Get tags with names filter using IN and expect two items in result");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(tag IN ('" + documentTag.getTag() + "', '" + folderTag.getTag() + "'))")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat()
|
||||
.entrySetMatches("tag", Set.of(documentTagValue, folderTagValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if alike name filter can be applied.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_whichNamesStartsWithOrphan()
|
||||
{
|
||||
STEP("Get tags with names filter using MATCHES and expect one item in result");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(tag MATCHES ('orphan*'))", "maxItems=10000")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat()
|
||||
.entrySetContains("tag", orphanTag.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that tags can be filtered by exact name and alike name at the same time.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withExactNameAndAlikeFilters()
|
||||
{
|
||||
STEP("Get tags with names filter using EQUALS and MATCHES and expect four items in result");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(tag MATCHES ('*tag*'))", "maxItems=10000")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat()
|
||||
.entrySetContains("tag", documentTagValue, documentTagValue2, folderTagValue, orphanTag.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if multiple alike filters can be applied.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withTwoAlikeFilters()
|
||||
{
|
||||
STEP("Get tags applying names filter using MATCHES twice and expect four items in result");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(tag MATCHES ('orphan*') OR tag MATCHES ('tag*'))", "maxItems=10000")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedCollection.assertThat()
|
||||
.entrySetContains("tag", documentTagValue, documentTagValue2, folderTagValue, orphanTag.getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that providing incorrect field name in where query will result with 400 (Bad Request).
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withWrongWherePropertyNameAndExpect400()
|
||||
{
|
||||
STEP("Try to get tags with names filter using EQUALS and wrong property name and expect 400");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(name=gat)")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary("Where query error: property with name: name is not expected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify tht AND operator is not supported in where query and expect 400 (Bad Request).
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_queryAndOperatorNotSupported()
|
||||
{
|
||||
STEP("Try to get tags applying names filter using AND operator and expect 400");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("where=(name=tag AND name IN ('tag-', 'gat'))")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary("An invalid WHERE query was received. Unsupported Predicate");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if count field is present for searched tags.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void testGetTags_includingCount()
|
||||
{
|
||||
STEP("Get tags including count and verify if it is present in the response");
|
||||
final RestTagModelsCollection searchedTags = restClient.withCoreAPI().include(FIELD_COUNT).getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
searchedTags.assertThat().entriesListIsNotEmpty()
|
||||
.assertThat().entriesListContains(FIELD_COUNT)
|
||||
.assertThat().entriesListContains(FIELD_TAG)
|
||||
.assertThat().entriesListContains(FIELD_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if count field is not present for searched tags.
|
||||
*/
|
||||
@Test(groups = {TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void testGetTags_notIncludingCount()
|
||||
{
|
||||
STEP("Get tags, not including count and verify if it is not in the response");
|
||||
final RestTagModelsCollection searchedTags = restClient.withCoreAPI().getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
searchedTags.assertThat().entriesListIsNotEmpty()
|
||||
.assertThat().entriesListDoesNotContain(FIELD_COUNT)
|
||||
.assertThat().entriesListContains(FIELD_TAG)
|
||||
.assertThat().entriesListContains(FIELD_ID);
|
||||
.and().entriesListDoesNotContain("tag", removedTag.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@ public class TagsDataPrep extends RestTest
|
||||
protected static ListUserWithRoles usersWithRoles;
|
||||
protected static SiteModel siteModel;
|
||||
protected static FileModel document;
|
||||
protected static FolderModel folder, folder2;
|
||||
protected static RestTagModelsCollection folder2tags;
|
||||
protected static FolderModel folder;
|
||||
protected static String documentTagValue, documentTagValue2, folderTagValue;
|
||||
protected static RestTagModel documentTag, documentTag2, folderTag, orphanTag, returnedModel;
|
||||
protected static RestTagModel documentTag, documentTag2, folderTag, returnedModel;
|
||||
protected static RestTagModelsCollection returnedCollection;
|
||||
|
||||
@BeforeClass
|
||||
@@ -39,29 +38,25 @@ public class TagsDataPrep extends RestTest
|
||||
usersWithRoles = dataUser.usingAdmin().addUsersWithRolesToSite(siteModel, UserRole.SiteManager, UserRole.SiteCollaborator, UserRole.SiteConsumer, UserRole.SiteContributor);
|
||||
document = dataContent.usingUser(adminUserModel).usingSite(siteModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
folder = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
folder2 = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
|
||||
documentTagValue = RandomData.getRandomName("tag").toLowerCase();
|
||||
documentTagValue2 = RandomData.getRandomName("tag").toLowerCase();
|
||||
folderTagValue = RandomData.getRandomName("tag").toLowerCase();
|
||||
documentTagValue = RandomData.getRandomName("tag");
|
||||
documentTagValue2 = RandomData.getRandomName("tag");
|
||||
folderTagValue = RandomData.getRandomName("tag");
|
||||
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
documentTag = restClient.withCoreAPI().usingResource(document).addTag(documentTagValue);
|
||||
documentTag2 = restClient.withCoreAPI().usingResource(document).addTag(documentTagValue2);
|
||||
folderTag = restClient.withCoreAPI().usingResource(folder).addTag(folderTagValue);
|
||||
orphanTag = restClient.withCoreAPI().createSingleTag(RestTagModel.builder().tag(RandomData.getRandomName("orphan-tag").toLowerCase()).create());
|
||||
folder2tags = restClient.withCoreAPI().usingResource(folder2).addTags(folderTagValue, documentTagValue);
|
||||
|
||||
// Allow indexing to complete.
|
||||
Utility.sleep(500, 60000, () ->
|
||||
{
|
||||
returnedCollection = restClient.withParams("maxItems=10000", "where=(tag MATCHES ('*tag*'))")
|
||||
.withCoreAPI().getTags();
|
||||
returnedCollection.assertThat().entriesListContains("tag", documentTagValue)
|
||||
.and().entriesListContains("tag", documentTagValue2)
|
||||
.and().entriesListContains("tag", folderTagValue)
|
||||
.and().entriesListContains("tag", orphanTag.getTag());
|
||||
});
|
||||
{
|
||||
returnedCollection = restClient.withParams("maxItems=10000").withCoreAPI().getTags();
|
||||
returnedCollection.assertThat().entriesListContains("tag", documentTagValue.toLowerCase())
|
||||
.and().entriesListContains("tag", documentTagValue2.toLowerCase())
|
||||
.and().entriesListContains("tag", folderTagValue.toLowerCase());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected RestTagModel createTagForDocument(FileModel document)
|
||||
@@ -82,9 +77,4 @@ public class TagsDataPrep extends RestTest
|
||||
.tag(tag)
|
||||
.create();
|
||||
}
|
||||
|
||||
protected RestTagModel createTagModelWithName(final String tagName)
|
||||
{
|
||||
return RestTagModel.builder().tag(tagName).create();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.alfresco.rest.tags;
|
||||
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
import org.alfresco.rest.model.RestErrorModel;
|
||||
import org.alfresco.rest.model.RestTagModel;
|
||||
import org.alfresco.utility.Utility;
|
||||
@@ -16,7 +13,6 @@ import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Ignore;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
@@ -29,29 +25,28 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
private String randomTag = "";
|
||||
|
||||
@BeforeMethod(alwaysRun=true)
|
||||
public void addTagToDocument()
|
||||
public void addTagToDocument() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
oldTag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("old").toLowerCase());
|
||||
randomTag = RandomData.getRandomName("tag").toLowerCase();
|
||||
oldTag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("old"));
|
||||
randomTag = RandomData.getRandomName("tag");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify Admin user updates tags and status code is 200")
|
||||
@Bug(id="REPO-1828")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void adminIsAbleToUpdateTags()
|
||||
public void adminIsAbleToUpdateTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingTag(oldTag).update(randomTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(randomTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API,
|
||||
TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify Manager user can't update tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void managerIsNotAbleToUpdateTag()
|
||||
public void managerIsNotAbleToUpdateTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
restClient.withCoreAPI().usingTag(oldTag).update(randomTag);
|
||||
@@ -61,7 +56,7 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Collaborator user can't update tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void collaboratorIsNotAbleToUpdateTagCheckDefaultErrorModelSchema()
|
||||
public void collaboratorIsNotAbleToUpdateTagCheckDefaultErrorModelSchema() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
restClient.withCoreAPI().usingTag(oldTag).update(randomTag);
|
||||
@@ -74,7 +69,7 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Contributor user can't update tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsNotAbleToUpdateTag()
|
||||
public void contributorIsNotAbleToUpdateTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor));
|
||||
restClient.withCoreAPI().usingTag(oldTag).update(randomTag);
|
||||
@@ -84,7 +79,7 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.SANITY, description = "Verify Consumer user can't update tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void consumerIsNotAbleToUpdateTag()
|
||||
public void consumerIsNotAbleToUpdateTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
restClient.withCoreAPI().usingTag(oldTag).update(randomTag);
|
||||
@@ -95,7 +90,7 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
executionType = ExecutionType.SANITY, description = "Verify user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void userIsNotAbleToUpdateTagIfAuthenticationFails()
|
||||
public void userIsNotAbleToUpdateTagIfAuthenticationFails() throws Exception
|
||||
{
|
||||
UserModel siteManager = usersWithRoles.getOneUserWithRole(UserRole.SiteManager);
|
||||
String managerPassword = siteManager.getPassword();
|
||||
@@ -108,140 +103,118 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify admin is not able to update tag with invalid id")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidId()
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidId() throws Exception
|
||||
{
|
||||
String invalidTagId = "invalid-id";
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag").toLowerCase());
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
tag.setId(invalidTagId);
|
||||
restClient.withCoreAPI().usingTag(tag).update(RandomData.getRandomName("tag").toLowerCase());
|
||||
restClient.withCoreAPI().usingTag(tag).update(RandomData.getRandomName("tag"));
|
||||
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND)
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, invalidTagId));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify admin is not able to update tag with empty id")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsNotAbleToUpdateTagWithEmptyId()
|
||||
public void adminIsNotAbleToUpdateTagWithEmptyId() throws Exception
|
||||
{
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag").toLowerCase());
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
tag.setId("");
|
||||
restClient.withCoreAPI().usingTag(tag).update(RandomData.getRandomName("tag").toLowerCase());
|
||||
restClient.withCoreAPI().usingTag(tag).update(RandomData.getRandomName("tag"));
|
||||
restClient.assertStatusCodeIs(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
.assertLastError().containsSummary(RestErrorModel.PUT_EMPTY_ARGUMENT);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify admin is not able to update tag with invalid body")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsNotAbleToUpdateTagWithEmptyBody()
|
||||
public void adminIsNotAbleToUpdateTagWithEmptyBody() throws Exception
|
||||
{
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag").toLowerCase());
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
restClient.withCoreAPI().usingTag(tag).update("");
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary(RestErrorModel.BLANK_TAG);
|
||||
.assertLastError().containsSummary(RestErrorModel.EMPTY_TAG);
|
||||
}
|
||||
|
||||
@Bug(id="ACE-5629")
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin is not able to update tag with invalid body containing '|' symbol")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Ignore
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidBodyScenario1()
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidBodyScenario1() throws Exception
|
||||
{
|
||||
String invalidTagBody = "|.\"/<>*";
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag").toLowerCase());
|
||||
try
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
Utility.sleep(500, 20000, () ->
|
||||
{
|
||||
Utility.sleep(500, 20000, () ->
|
||||
{
|
||||
restClient.withCoreAPI().usingTag(tag).update(invalidTagBody);
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_TAG, invalidTagBody));
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
fail("Test interrupted while waiting for error status code.");
|
||||
}
|
||||
restClient.withCoreAPI().usingTag(tag).update(invalidTagBody);
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_TAG, invalidTagBody));
|
||||
});
|
||||
}
|
||||
|
||||
@Bug(id="ACE-5629")
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin is not able to update tag with invalid body without '|' symbol")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Ignore
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidBodyScenario2()
|
||||
public void adminIsNotAbleToUpdateTagWithInvalidBodyScenario2() throws Exception
|
||||
{
|
||||
String invalidTagBody = ".\"/<>*";
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
try
|
||||
{
|
||||
Utility.sleep(500, 20000, () ->
|
||||
{
|
||||
restClient.withCoreAPI().usingTag(tag).update(invalidTagBody);
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
restClient.withCoreAPI().usingTag(tag).update(invalidTagBody);
|
||||
restClient.assertStatusCodeIs(HttpStatus.BAD_REQUEST)
|
||||
.assertLastError().containsSummary(String.format(RestErrorModel.INVALID_TAG, invalidTagBody));
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
fail("Test interrupted while waiting for error status code.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user can provide large string for new tag value.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
@Ignore
|
||||
public void adminIsAbleToUpdateTagsProvideLargeStringTag()
|
||||
public void adminIsAbleToUpdateTagsProvideLargeStringTag() throws Exception
|
||||
{
|
||||
String largeStringTag = RandomStringUtils.randomAlphanumeric(10000).toLowerCase();
|
||||
String largeStringTag = RandomStringUtils.randomAlphanumeric(10000);
|
||||
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingTag(oldTag).update(largeStringTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(largeStringTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user can provide short string for new tag value.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
public void adminIsAbleToUpdateTagsProvideShortStringTag()
|
||||
public void adminIsAbleToUpdateTagsProvideShortStringTag() throws Exception
|
||||
{
|
||||
String shortStringTag = RandomStringUtils.randomAlphanumeric(2).toLowerCase();
|
||||
String shortStringTag = RandomStringUtils.randomAlphanumeric(2);
|
||||
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingTag(oldTag).update(shortStringTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(shortStringTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user can provide string with special chars for new tag value.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
@Ignore
|
||||
public void adminIsAbleToUpdateTagsProvideSpecialCharsStringTag()
|
||||
public void adminIsAbleToUpdateTagsProvideSpecialCharsStringTag() throws Exception
|
||||
{
|
||||
String specialCharsString = RandomData.getRandomName("!@#$%^&*()'\".,<>-_+=|\\").toLowerCase();
|
||||
String specialCharsString = "!@#$%^&*()'\".,<>-_+=|\\";
|
||||
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingTag(oldTag).update(specialCharsString);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(specialCharsString);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user can provide existing tag for new tag value.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
@Ignore
|
||||
public void adminIsAbleToUpdateTagsProvideExistingTag()
|
||||
public void adminIsAbleToUpdateTagsProvideExistingTag() throws Exception
|
||||
{
|
||||
String existingTag = RandomData.getRandomName("oldTag").toLowerCase();
|
||||
String existingTag = "oldTag";
|
||||
RestTagModel oldExistingTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager))
|
||||
.withCoreAPI().usingResource(document).addTag(existingTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.CREATED);
|
||||
@@ -250,43 +223,38 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
returnedModel = restClient.withCoreAPI().usingTag(oldExistingTag).update(existingTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(existingTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user can delete a tag, add tag and update it.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
@Ignore
|
||||
public void adminDeleteTagAddTagUpdateTag()
|
||||
public void adminDeleteTagAddTagUpdateTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel)
|
||||
.withCoreAPI().usingResource(document).deleteTag(oldTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT);
|
||||
|
||||
String newTag = RandomData.getRandomName("addTag").toLowerCase();
|
||||
String newTag = "addTag";
|
||||
RestTagModel newTagModel = restClient.withCoreAPI().usingResource(document).addTag(newTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.CREATED);
|
||||
|
||||
returnedModel = restClient.withCoreAPI().usingTag(newTagModel).update(newTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(newTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user can update a tag, delete tag and add it.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id="REPO-1828")
|
||||
@Ignore
|
||||
public void adminUpdateTagDeleteTagAddTag()
|
||||
public void adminUpdateTagDeleteTagAddTag() throws Exception
|
||||
{
|
||||
String newTag = RandomData.getRandomName("addTag").toLowerCase();
|
||||
String newTag = "addTag";
|
||||
|
||||
returnedModel = restClient.authenticateUser(adminUserModel).withCoreAPI().usingTag(oldTag).update(newTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
returnedModel.assertThat().field("tag").is(newTag);
|
||||
returnedModel.assertThat().field("id").isNotNull();
|
||||
|
||||
restClient.withCoreAPI().usingResource(document).deleteTag(returnedModel);
|
||||
restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT);
|
||||
@@ -294,35 +262,4 @@ public class UpdateTagTests extends TagsDataPrep
|
||||
restClient.withCoreAPI().usingResource(document).addTag(newTag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY,
|
||||
description = "Verify Admin user updates orphan tags and status code is 200")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void adminIsAbleToUpdateOrphanTag()
|
||||
{
|
||||
STEP("Update orphan tag and expect 200");
|
||||
final String newTagName = RandomData.getRandomName("new").toLowerCase();
|
||||
returnedModel = restClient.authenticateUser(adminUserModel).withCoreAPI().usingTag(orphanTag).update(newTagName);
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
RestTagModel expected = RestTagModel.builder().id(orphanTag.getId()).tag(newTagName).create();
|
||||
returnedModel.assertThat().isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.TAGS })
|
||||
public void canUpdateTagAndGetCount()
|
||||
{
|
||||
STEP("Create an orphaned tag");
|
||||
String tagName = RandomData.getRandomName("tag").toLowerCase();
|
||||
RestTagModel createdTag = RestTagModel.builder().tag(tagName).create();
|
||||
RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(createdTag);
|
||||
|
||||
STEP("Update tag and request the count field");
|
||||
String newTagName = RandomData.getRandomName("new").toLowerCase();
|
||||
returnedModel = restClient.authenticateUser(adminUserModel).withCoreAPI().include("count").usingTag(tag).update(newTagName);
|
||||
|
||||
restClient.assertStatusCodeIs(HttpStatus.OK);
|
||||
RestTagModel expected = RestTagModel.builder().id(tag.getId()).tag(newTagName).count(0).create();
|
||||
returnedModel.assertThat().isEqualTo(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,13 @@ public class AddTagTests extends TagsDataPrep
|
||||
@BeforeMethod(alwaysRun = true)
|
||||
public void generateRandomTag()
|
||||
{
|
||||
tagValue = RandomData.getRandomName("tag").toLowerCase();
|
||||
tagValue = RandomData.getRandomName("tag");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user adds tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsAbleToAddTag()
|
||||
public void adminIsAbleToAddTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -51,7 +51,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY,
|
||||
description = "Verify Manager user adds tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void managerIsAbleToTagAFile()
|
||||
public void managerIsAbleToTagAFile() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -63,7 +63,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Collaborator user adds tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void collaboratorIsAbleToTagAFile()
|
||||
public void collaboratorIsAbleToTagAFile() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -75,7 +75,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user doesn't have permission to add tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsNotAbleToAddTagToAnotherContent()
|
||||
public void contributorIsNotAbleToAddTagToAnotherContent() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor));
|
||||
restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -85,7 +85,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user adds tags to his content with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsAbleToAddTagToHisContent()
|
||||
public void contributorIsAbleToAddTagToHisContent() throws Exception
|
||||
{
|
||||
userModel = usersWithRoles.getOneUserWithRole(UserRole.SiteContributor);
|
||||
restClient.authenticateUser(userModel);
|
||||
@@ -99,7 +99,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Consumer user doesn't have permission to add tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void consumerIsNotAbleToTagAFile()
|
||||
public void consumerIsNotAbleToTagAFile() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer));
|
||||
restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -110,7 +110,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
description = "Verify user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void userIsNotAbleToAddTagIfAuthenticationFails()
|
||||
public void userIsNotAbleToAddTagIfAuthenticationFails() throws Exception
|
||||
{
|
||||
UserModel siteManager = usersWithRoles.getOneUserWithRole(UserRole.SiteManager);
|
||||
String managerPassword = siteManager.getPassword();
|
||||
@@ -124,7 +124,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that adding empty tag returns status code 400")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void emptyTagTest()
|
||||
public void emptyTagTest() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag("");
|
||||
@@ -134,7 +134,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that adding tag with user that has no permissions returns status code 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagWithUserThatDoesNotHavePermissions()
|
||||
public void addTagWithUserThatDoesNotHavePermissions() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(dataUser.createRandomTestUser());
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag(tagValue);
|
||||
@@ -144,7 +144,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that adding tag to a node that does not exist returns status code 404")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagToInexistentNode()
|
||||
public void addTagToInexistentNode() throws Exception
|
||||
{
|
||||
String oldNodeRef = document.getNodeRef();
|
||||
String nodeRef = RandomStringUtils.randomAlphanumeric(10);
|
||||
@@ -159,7 +159,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY,
|
||||
description = "Verify that manager is able to tag a folder")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void managerIsAbleToTagAFolder()
|
||||
public void managerIsAbleToTagAFolder() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
@@ -171,7 +171,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that tagged file can be tagged again")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagToATaggedFile()
|
||||
public void addTagToATaggedFile() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
|
||||
@@ -195,7 +195,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that user cannot add invalid tag")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addInvalidTag()
|
||||
public void addInvalidTag() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag("-1~!|@#$%^&*()_=");
|
||||
@@ -205,7 +205,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that contributor is able to tag a folder created by self")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsAbleToTagAFolderCreatedBySelf()
|
||||
public void contributorIsAbleToTagAFolderCreatedBySelf() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor)).usingSite(siteModel).createFolder();
|
||||
|
||||
@@ -218,7 +218,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that collaborator is able to tag a folder")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void collaboratorIsAbleToTagAFolder()
|
||||
public void collaboratorIsAbleToTagAFolder() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
|
||||
@@ -231,7 +231,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that consumer is not able to tag a folder. Check default error model schema.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void consumerIsNotAbleToTagAFolder()
|
||||
public void consumerIsNotAbleToTagAFolder() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
|
||||
@@ -246,7 +246,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that tagged folder can be tagged again")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagToATaggedFolder()
|
||||
public void addTagToATaggedFolder() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
|
||||
@@ -269,11 +269,11 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Using collaborator provide more than one tag element")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void provideMoreThanOneTagElement()
|
||||
public void provideMoreThanOneTagElement() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
String tagValue1 = RandomData.getRandomName("tag1").toLowerCase();
|
||||
String tagValue2 = RandomData.getRandomName("tag2").toLowerCase();
|
||||
String tagValue1 = RandomData.getRandomName("tag1");
|
||||
String tagValue2 = RandomData.getRandomName("tag2");
|
||||
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
|
||||
@@ -288,7 +288,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that manager cannot add tag with special characters.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagWithSpecialCharacters()
|
||||
public void addTagWithSpecialCharacters() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
String specialCharsTag = "!@#$%^&*()'\".,<>-_+=|\\";
|
||||
@@ -301,7 +301,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that you cannot tag a comment and it returns status code 405")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagToAComment()
|
||||
public void addTagToAComment() throws Exception
|
||||
{
|
||||
FileModel file = dataContent.usingSite(siteModel).usingUser(adminUserModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
String comment = "comment for a tag";
|
||||
@@ -316,7 +316,7 @@ public class AddTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that you cannot tag a tag and it returns status code 405")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void addTagToATag()
|
||||
public void addTagToATag() throws Exception
|
||||
{
|
||||
FileModel file = dataContent.usingSite(siteModel).usingUser(adminUserModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
@@ -326,17 +326,4 @@ public class AddTagTests extends TagsDataPrep
|
||||
restClient.withCoreAPI().usingResource(file).addTag(tagValue);
|
||||
restClient.assertStatusCodeIs(HttpStatus.METHOD_NOT_ALLOWED).assertLastError().containsSummary(RestErrorModel.CANNOT_TAG);
|
||||
}
|
||||
|
||||
@TestRail (section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify the tag name is converted to lower case before being applied")
|
||||
@Test (groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void tagNameIsConvertedToLowerCase()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
String tagName = RandomData.getRandomName("TaG-oNe");
|
||||
returnedModel = restClient.withCoreAPI().usingResource(document).addTag(tagName);
|
||||
restClient.assertStatusCodeIs(HttpStatus.CREATED);
|
||||
returnedModel.assertThat().field("tag").is(tagName.toLowerCase())
|
||||
.and().field("id").isNotEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,14 +30,14 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@BeforeMethod(alwaysRun = true)
|
||||
public void generateRandomTagsList()
|
||||
{
|
||||
tag1 = RandomData.getRandomName("tag").toLowerCase();
|
||||
tag2 = RandomData.getRandomName("tag").toLowerCase();
|
||||
tag1 = RandomData.getRandomName("tag");
|
||||
tag2 = RandomData.getRandomName("tag");
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify admin user adds multiple tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsAbleToAddTags()
|
||||
public void adminIsAbleToAddTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
returnedCollection = restClient.withCoreAPI().usingResource(document).addTags(tag1, tag2);
|
||||
@@ -49,7 +49,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY,
|
||||
description = "Verify Manager user adds multiple tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void managerIsAbleToAddTags()
|
||||
public void managerIsAbleToAddTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager));
|
||||
returnedCollection = restClient.withCoreAPI().usingResource(document).addTags(tag1, tag2);
|
||||
@@ -61,7 +61,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.SANITY, description = "Verify Collaborator user adds multiple tags with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void collaboratorIsAbleToAddTags()
|
||||
public void collaboratorIsAbleToAddTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator));
|
||||
returnedCollection = restClient.withCoreAPI().usingResource(document).addTags(tag1, tag2);
|
||||
@@ -73,7 +73,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user doesn't have permission to add multiple tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsNotAbleToAddTagsToAnotherContent()
|
||||
public void contributorIsNotAbleToAddTagsToAnotherContent() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor));
|
||||
restClient.withCoreAPI().usingResource(document).addTags(tag1, tag2);
|
||||
@@ -83,7 +83,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user adds multiple tags to his content with Rest API and status code is 201")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsAbleToAddTagsToHisContent()
|
||||
public void contributorIsAbleToAddTagsToHisContent() throws Exception
|
||||
{
|
||||
userModel = usersWithRoles.getOneUserWithRole(UserRole.SiteContributor);
|
||||
restClient.authenticateUser(userModel);
|
||||
@@ -97,7 +97,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Consumer user doesn't have permission to add multiple tags with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void consumerIsNotAbleToAddTags()
|
||||
public void consumerIsNotAbleToAddTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer)).withCoreAPI().usingResource(document).addTags(tag1, tag2);
|
||||
restClient.assertStatusCodeIs(HttpStatus.FORBIDDEN).assertLastError().containsSummary(RestErrorModel.PERMISSION_WAS_DENIED);
|
||||
@@ -107,7 +107,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
description = "Verify user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void userIsNotAbleToAddTagsIfAuthenticationFails()
|
||||
public void userIsNotAbleToAddTagsIfAuthenticationFails() throws Exception
|
||||
{
|
||||
UserModel siteManager = usersWithRoles.getOneUserWithRole(UserRole.SiteManager);
|
||||
String managerPassword = siteManager.getPassword();
|
||||
@@ -120,7 +120,7 @@ public class AddTagsTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API,
|
||||
TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify include count parameter")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void getTagsUsingCountParam()
|
||||
public void getTagsUsingCountParam() throws Exception
|
||||
{
|
||||
FileModel file = dataContent.usingSite(siteModel).usingUser(adminUserModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
String tagName = RandomData.getRandomName("tag");
|
||||
@@ -139,4 +139,4 @@ public class AddTagsTests extends TagsDataPrep
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import org.alfresco.utility.testrail.ExecutionType;
|
||||
import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.Ignore;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
@@ -30,7 +29,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Admin user deletes tags with Rest API and status code is 204")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminIsAbleToDeleteTags()
|
||||
public void adminIsAbleToDeleteTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -44,7 +43,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY,
|
||||
description = "Verify Manager user deletes tags created by admin user with Rest API and status code is 204")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
public void managerIsAbleToDeleteTags()
|
||||
public void managerIsAbleToDeleteTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -57,7 +56,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Collaborator user deletes tags created by admin user with Rest API and status code is 204")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void collaboratorIsAbleToDeleteTags()
|
||||
public void collaboratorIsAbleToDeleteTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -70,7 +69,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user can't delete tags created by admin user with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsNotAbleToDeleteTagsForAnotherUserContent()
|
||||
public void contributorIsNotAbleToDeleteTagsForAnotherUserContent() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -83,7 +82,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Contributor user deletes tags created by him with Rest API and status code is 204")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void contributorIsAbleToDeleteTagsForHisContent()
|
||||
public void contributorIsAbleToDeleteTagsForHisContent() throws Exception
|
||||
{
|
||||
userModel = usersWithRoles.getOneUserWithRole(UserRole.SiteContributor);
|
||||
restClient.authenticateUser(userModel);
|
||||
@@ -97,7 +96,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify Consumer user can't delete tags created by admin user with Rest API and status code is 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void consumerIsNotAbleToDeleteTags()
|
||||
public void consumerIsNotAbleToDeleteTags() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -111,7 +110,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
description = "Verify user gets status code 401 if authentication call fails")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
public void userIsNotAbleToDeleteTagIfAuthenticationFails()
|
||||
public void userIsNotAbleToDeleteTagIfAuthenticationFails() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -128,7 +127,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if user has no permission to remove tag returned status code is 403. Check default error model schema")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void deleteTagWithUserWithoutPermissionCheckDefaultErrorModelSchema()
|
||||
public void deleteTagWithUserWithoutPermissionCheckDefaultErrorModelSchema() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
RestTagModel tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -145,7 +144,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if node does not exist returned status code is 404")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void deleteTagForANonexistentNode()
|
||||
public void deleteTagForANonexistentNode() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
RestTagModel tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -160,7 +159,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if tag does not exist returned status code is 404")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void deleteTagThatDoesNotExist()
|
||||
public void deleteTagThatDoesNotExist() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
RestTagModel tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -173,7 +172,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if tag id is empty returned status code is 405")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void deleteTagWithEmptyId()
|
||||
public void deleteTagWithEmptyId() throws Exception
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
RestTagModel tag = restClient.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -186,7 +185,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that folder tag can be deleted")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void deleteFolderTag()
|
||||
public void deleteFolderTag() throws Exception
|
||||
{
|
||||
FolderModel folderModel = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();;
|
||||
restClient.authenticateUser(adminUserModel);
|
||||
@@ -201,8 +200,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Manager user can't delete deleted tag.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
@Bug(id = "ACE-5455")
|
||||
@Ignore
|
||||
public void managerCannotDeleteDeletedTag()
|
||||
public void managerCannotDeleteDeletedTag() throws Exception
|
||||
{
|
||||
tag = restClient.authenticateUser(adminUserModel)
|
||||
.withCoreAPI().usingResource(document).addTag(RandomData.getRandomName("tag"));
|
||||
@@ -218,7 +216,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Collaborator user can delete long tag.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void userCollaboratorCanDeleteLongTag()
|
||||
public void userCollaboratorCanDeleteLongTag() throws Exception
|
||||
{
|
||||
String longTag = RandomStringUtils.randomAlphanumeric(800);
|
||||
|
||||
@@ -233,7 +231,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Manager user can delete short tag.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void managerCanDeleteShortTag()
|
||||
public void managerCanDeleteShortTag() throws Exception
|
||||
{
|
||||
String shortTag = RandomStringUtils.randomAlphanumeric(10);
|
||||
|
||||
@@ -248,7 +246,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Admin can delete tag then add it again.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void adminRemovesTagAndAddsItAgain()
|
||||
public void adminRemovesTagAndAddsItAgain() throws Exception
|
||||
{
|
||||
String tagValue = RandomStringUtils.randomAlphanumeric(10);
|
||||
|
||||
@@ -269,7 +267,7 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS },
|
||||
executionType = ExecutionType.REGRESSION, description = "Verify Manager user can delete tag added by another user.")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void managerCanDeleteTagAddedByAnotherUser()
|
||||
public void managerCanDeleteTagAddedByAnotherUser() throws Exception
|
||||
{
|
||||
tag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator))
|
||||
.withCoreAPI().usingResource(document).addTag(RandomStringUtils.randomAlphanumeric(10));
|
||||
@@ -278,4 +276,4 @@ public class DeleteTagTests extends TagsDataPrep
|
||||
.withCoreAPI().usingResource(document).deleteTag(tag);
|
||||
restClient.assertStatusCodeIs(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,18 @@ public class GetNodeTagsTests extends TagsDataPrep
|
||||
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND).assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, nodeRef));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify that if node id is empty returns status code 403")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
public void emptyNodeIdTest() throws Exception
|
||||
{
|
||||
FileModel badDocument = dataContent.usingSite(siteModel).usingUser(adminUserModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
badDocument.setNodeRef("");
|
||||
|
||||
restClient.authenticateUser(adminUserModel).withCoreAPI().usingResource(badDocument).getNodeTags();
|
||||
restClient.assertStatusCodeIs(HttpStatus.NOT_FOUND).assertLastError().containsSummary(String.format(RestErrorModel.ENTITY_NOT_FOUND, ""));
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
description = "Verify folder tags")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION})
|
||||
@@ -291,4 +303,4 @@ public class GetNodeTagsTests extends TagsDataPrep
|
||||
.and().field("skipCount").is("10000");
|
||||
returnedCollection.assertThat().entriesListCountIs(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -30,6 +30,10 @@
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-trashcan-cleaner</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco.services</groupId>
|
||||
<artifactId>alfresco-messaging-repo</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xalan</groupId>
|
||||
<artifactId>xalan</artifactId>
|
||||
@@ -136,7 +140,7 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
|
||||
126
pom.xml
126
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<acs.version.major>23</acs.version.major>
|
||||
<acs.version.minor>1</acs.version.minor>
|
||||
<acs.version.major>7</acs.version.major>
|
||||
<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>
|
||||
@@ -38,30 +38,31 @@
|
||||
<builder.name>entitled-builder</builder.name>
|
||||
<local.registry>127.0.0.1:5000</local.registry>
|
||||
|
||||
<java.version>17</java.version>
|
||||
<java.version>11</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven.build.sourceVersion>${java.version}</maven.build.sourceVersion>
|
||||
|
||||
<dir.root>${project.build.directory}/alf_data</dir.root>
|
||||
|
||||
<dependency.alfresco-hb-data-sender.version>1.1.1</dependency.alfresco-hb-data-sender.version>
|
||||
<dependency.alfresco-trashcan-cleaner.version>2.4.2</dependency.alfresco-trashcan-cleaner.version>
|
||||
<dependency.alfresco-jlan.version>7.5</dependency.alfresco-jlan.version>
|
||||
<dependency.alfresco-hb-data-sender.version>1.0.12</dependency.alfresco-hb-data-sender.version>
|
||||
<dependency.alfresco-trashcan-cleaner.version>2.4.1</dependency.alfresco-trashcan-cleaner.version>
|
||||
<dependency.alfresco-jlan.version>7.4</dependency.alfresco-jlan.version>
|
||||
<dependency.alfresco-server-root.version>6.0.1</dependency.alfresco-server-root.version>
|
||||
<dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.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.2.0-A1</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>3.2.0-A1</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-greenmail.version>6.9</dependency.alfresco-greenmail.version>
|
||||
<dependency.acs-event-model.version>0.0.22</dependency.acs-event-model.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.18</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.spring.version>5.3.27</dependency.spring.version>
|
||||
<dependency.spring.version>5.3.25</dependency.spring.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
<dependency.jackson.version>2.15.1</dependency.jackson.version>
|
||||
<dependency.jackson.version>2.14.0</dependency.jackson.version>
|
||||
<dependency.cxf.version>3.5.5</dependency.cxf.version>
|
||||
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
|
||||
<dependency.webscripts.version>8.42</dependency.webscripts.version>
|
||||
<dependency.webscripts.version>8.33</dependency.webscripts.version>
|
||||
<dependency.bouncycastle.version>1.70</dependency.bouncycastle.version>
|
||||
<dependency.mockito-core.version>4.9.0</dependency.mockito-core.version>
|
||||
<dependency.assertj.version>3.24.2</dependency.assertj.version>
|
||||
@@ -70,29 +71,30 @@
|
||||
<dependency.commons-io.version>2.11.0</dependency.commons-io.version>
|
||||
<dependency.gson.version>2.8.9</dependency.gson.version>
|
||||
<dependency.httpclient.version>4.5.13</dependency.httpclient.version>
|
||||
<dependency.httpcore.version>4.4.16</dependency.httpcore.version>
|
||||
<dependency.httpcore.version>4.4.15</dependency.httpcore.version>
|
||||
<dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version>
|
||||
<dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version>
|
||||
<dependency.slf4j.version>2.0.7</dependency.slf4j.version>
|
||||
<dependency.log4j.version>2.20.0</dependency.log4j.version>
|
||||
<dependency.gytheio.version>0.20.0-A1</dependency.gytheio.version>
|
||||
<dependency.groovy.version>3.0.17</dependency.groovy.version>
|
||||
<dependency.slf4j.version>2.0.3</dependency.slf4j.version>
|
||||
<dependency.log4j.version>2.19.0</dependency.log4j.version>
|
||||
<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.8.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.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.20.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
|
||||
<dependency.netty.version>4.1.87.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common -->
|
||||
<dependency.netty.qpid.version>4.1.82.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.56.Final</dependency.netty-tcnative.version> <!-- must be in sync with camels transitive dependencies -->
|
||||
<dependency.camel.version>3.18.2</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies -->
|
||||
<dependency.netty.version>4.1.79.Final</dependency.netty.version> <!-- must be in sync with camels transitive dependencies, e.g.: netty-common -->
|
||||
<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.4</dependency.activemq.version>
|
||||
<dependency.apache-compress.version>1.23.0</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.66</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>
|
||||
@@ -106,26 +108,25 @@
|
||||
<dependency.jakarta-jws-api.version>2.1.0</dependency.jakarta-jws-api.version>
|
||||
<dependency.jakarta-mail-api.version>1.6.5</dependency.jakarta-mail-api.version>
|
||||
<dependency.jakarta-json-api.version>1.1.6</dependency.jakarta-json-api.version>
|
||||
<dependency.jakarta-json-path.version>2.8.0</dependency.jakarta-json-path.version>
|
||||
<dependency.json-smart.version>2.4.11</dependency.json-smart.version>
|
||||
<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.5.0-A2</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.6.1-A1</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>23.1.0-A1</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
<alfresco.googledrive.version>3.4.0-M1</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.6.0-M1</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</license-maven-plugin.version>
|
||||
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
|
||||
|
||||
<dependency.postgresql.version>42.6.0</dependency.postgresql.version>
|
||||
<dependency.postgresql.version>42.5.2</dependency.postgresql.version>
|
||||
<dependency.mysql.version>8.0.30</dependency.mysql.version>
|
||||
<dependency.mysql-image.version>8</dependency.mysql-image.version>
|
||||
<dependency.mariadb.version>2.7.4</dependency.mariadb.version>
|
||||
<dependency.tas-utility.version>4.0.3</dependency.tas-utility.version>
|
||||
<dependency.rest-assured.version>5.3.0</dependency.rest-assured.version>
|
||||
<dependency.tas-email.version>1.21</dependency.tas-email.version>
|
||||
<dependency.tas-webdav.version>1.16</dependency.tas-webdav.version>
|
||||
<dependency.tas-ftp.version>1.17</dependency.tas-ftp.version>
|
||||
<dependency.tas-utility.version>3.0.61</dependency.tas-utility.version>
|
||||
<dependency.rest-assured.version>5.2.0</dependency.rest-assured.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>
|
||||
|
||||
<!-- AGS properties shared between community and enterprise -->
|
||||
@@ -149,7 +150,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>23.1.0.133</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -240,17 +241,6 @@
|
||||
<version>${dependency.jakarta-json-api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<version>${dependency.jakarta-json-path.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId> net.minidev</groupId>
|
||||
<artifactId>json-smart</artifactId>
|
||||
<version>${dependency.json-smart.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.rpc</groupId>
|
||||
<artifactId>jakarta.xml.rpc-api</artifactId>
|
||||
@@ -296,6 +286,17 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco.services</groupId>
|
||||
<artifactId>alfresco-messaging-repo</artifactId>
|
||||
<version>${dependency.alfresco-messaging-repo.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-broker</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-server-root</artifactId>
|
||||
@@ -517,7 +518,7 @@
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>2.0</version>
|
||||
<version>1.32</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -645,7 +646,7 @@
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.15.3</version>
|
||||
</dependency>
|
||||
<!-- upgrade dependency from TIKA -->
|
||||
<dependency>
|
||||
@@ -729,7 +730,7 @@
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>2.12.5</version>
|
||||
<version>2.12.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- provided dependencies -->
|
||||
@@ -886,7 +887,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.26</version>
|
||||
<version>1.18.24</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -900,13 +901,6 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-bom</artifactId>
|
||||
<version>${dependency.spring-security.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -924,7 +918,7 @@
|
||||
<plugin>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<version>0.43.0</version>
|
||||
<version>0.42.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
@@ -945,21 +939,21 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.4.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.1</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.6.0</version>
|
||||
<version>3.4.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.alfresco.maven.plugin</groupId>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -47,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.santuario</groupId>
|
||||
<artifactId>xmlsec</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
<!-- newer version, see REPO-3133 -->
|
||||
<dependency>
|
||||
@@ -130,7 +130,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>10.0.14</version>
|
||||
<version>10.0.11</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -154,7 +154,7 @@
|
||||
<dependency>
|
||||
<groupId>org.alfresco.cmis.client</groupId>
|
||||
<artifactId>alfresco-opencmis-extension</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>2.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<!-- Duplicates classes from jakarta.transaction:jakarta.transaction-api -->
|
||||
|
||||
@@ -32,8 +32,10 @@ import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
|
||||
@Experimental
|
||||
public interface Categories
|
||||
{
|
||||
Category getCategoryById(StoreRef storeRef, String id, Parameters parameters);
|
||||
|
||||
@@ -39,8 +39,6 @@ import org.alfresco.rest.api.model.LockInfo;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.api.model.PathInfo;
|
||||
import org.alfresco.rest.api.model.UserInfo;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.resource.content.BasicContentInfo;
|
||||
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
@@ -210,19 +208,6 @@ public interface Nodes
|
||||
NodeRef validateNode(StoreRef storeRef, String nodeId);
|
||||
NodeRef validateNode(String nodeId);
|
||||
NodeRef validateNode(NodeRef nodeRef);
|
||||
|
||||
/**
|
||||
* Check that the specified id refers to a valid node.
|
||||
*
|
||||
* @param nodeId The node id to look up using SpacesStore or an alias like -root-.
|
||||
* @return The node ref.
|
||||
* @throws InvalidArgumentException if the specified node id is not a valid format.
|
||||
* @throws EntityNotFoundException if the specified node was not found in the database.
|
||||
*/
|
||||
default NodeRef validateOrLookupNode(String nodeId)
|
||||
{
|
||||
return validateOrLookupNode(nodeId, null);
|
||||
}
|
||||
NodeRef validateOrLookupNode(String nodeId, String path);
|
||||
|
||||
boolean nodeMatches(NodeRef nodeRef, Set<QName> expectedTypes, Set<QName> excludedTypes);
|
||||
|
||||
@@ -32,19 +32,22 @@ import java.util.List;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
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.StoreRef;
|
||||
|
||||
public interface Tags
|
||||
{
|
||||
List<Tag> addTags(String nodeId, List<Tag> tags, Parameters parameters);
|
||||
Tag getTag(StoreRef storeRef, String tagId, Parameters parameters);
|
||||
List<Tag> addTags(String nodeId, List<Tag> tags);
|
||||
Tag getTag(StoreRef storeRef, String tagId);
|
||||
void deleteTag(String nodeId, String tagId);
|
||||
CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params);
|
||||
Tag changeTag(StoreRef storeRef, String tagId, Tag tag, Parameters parameters);
|
||||
Tag changeTag(StoreRef storeRef, String tagId, Tag tag);
|
||||
CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params);
|
||||
|
||||
@Experimental
|
||||
List<Tag> createTags(StoreRef storeRef, List<Tag> tags, Parameters parameters);
|
||||
|
||||
@Experimental
|
||||
default List<Tag> createTags(List<Tag> tags, Parameters parameters)
|
||||
{
|
||||
return createTags(STORE_REF_WORKSPACE_SPACESSTORE, tags, parameters);
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
@@ -64,6 +65,7 @@ import org.alfresco.util.TypeConstraint;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@Experimental
|
||||
public class CategoriesImpl implements Categories
|
||||
{
|
||||
static final String INCLUDE_COUNT_PARAM = "count";
|
||||
@@ -109,11 +111,6 @@ public class CategoriesImpl implements Categories
|
||||
category.setCount(categoriesCount.getOrDefault(category.getId(), 0));
|
||||
}
|
||||
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
@@ -131,10 +128,6 @@ public class CategoriesImpl implements Categories
|
||||
{
|
||||
category.setCount(0);
|
||||
}
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
@@ -143,18 +136,11 @@ public class CategoriesImpl implements Categories
|
||||
public List<Category> getCategoryChildren(final StoreRef storeRef, final String parentCategoryId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef parentNodeRef = getCategoryNodeRef(storeRef, parentCategoryId);
|
||||
final List<Category> categories = nodeService.getChildAssocs(parentNodeRef)
|
||||
.stream()
|
||||
.filter(ca -> ContentModel.ASSOC_SUBCATEGORIES.equals(ca.getTypeQName()))
|
||||
.map(ChildAssociationRef::getChildRef)
|
||||
.map(this::mapToCategory)
|
||||
.peek(category -> {
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
final List<Category> categories = nodeService.getChildAssocs(parentNodeRef).stream()
|
||||
.filter(ca -> ContentModel.ASSOC_SUBCATEGORIES.equals(ca.getTypeQName()))
|
||||
.map(ChildAssociationRef::getChildRef)
|
||||
.map(this::mapToCategory)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (parameters.getInclude().contains(INCLUDE_COUNT_PARAM))
|
||||
{
|
||||
@@ -184,11 +170,6 @@ public class CategoriesImpl implements Categories
|
||||
category.setCount(categoriesCount.getOrDefault(category.getId(), 0));
|
||||
}
|
||||
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
@@ -208,7 +189,7 @@ public class CategoriesImpl implements Categories
|
||||
@Override
|
||||
public List<Category> listCategoriesForNode(final String nodeId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef contentNodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
final NodeRef contentNodeRef = nodes.validateNode(nodeId);
|
||||
verifyReadPermission(contentNodeRef);
|
||||
verifyNodeType(contentNodeRef);
|
||||
|
||||
@@ -219,16 +200,7 @@ public class CategoriesImpl implements Categories
|
||||
}
|
||||
final Collection<NodeRef> actualCategories = DefaultTypeConverter.INSTANCE.getCollection(NodeRef.class, currentCategories);
|
||||
|
||||
return actualCategories
|
||||
.stream()
|
||||
.map(this::mapToCategory)
|
||||
.peek(category -> {
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return actualCategories.stream().map(this::mapToCategory).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,7 +211,7 @@ public class CategoriesImpl implements Categories
|
||||
throw new InvalidArgumentException(NOT_A_VALID_CATEGORY);
|
||||
}
|
||||
|
||||
final NodeRef contentNodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
final NodeRef contentNodeRef = nodes.validateNode(nodeId);
|
||||
verifyChangePermission(contentNodeRef);
|
||||
verifyNodeType(contentNodeRef);
|
||||
|
||||
@@ -258,23 +230,14 @@ public class CategoriesImpl implements Categories
|
||||
|
||||
linkNodeToCategories(contentNodeRef, categoryNodeRefs);
|
||||
|
||||
return categoryNodeRefs
|
||||
.stream()
|
||||
.map(this::mapToCategory)
|
||||
.peek(category -> {
|
||||
if (parameters.getInclude().contains(Nodes.PARAM_INCLUDE_PATH))
|
||||
{
|
||||
category.setPath(getCategoryPath(category));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return categoryNodeRefs.stream().map(this::mapToCategory).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlinkNodeFromCategory(final StoreRef storeRef, final String nodeId, final String categoryId, final Parameters parameters)
|
||||
{
|
||||
final NodeRef categoryNodeRef = getCategoryNodeRef(storeRef, categoryId);
|
||||
final NodeRef contentNodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
final NodeRef contentNodeRef = nodes.validateNode(nodeId);
|
||||
verifyChangePermission(contentNodeRef);
|
||||
verifyNodeType(contentNodeRef);
|
||||
|
||||
@@ -512,16 +475,4 @@ public class CategoriesImpl implements Categories
|
||||
.stream()
|
||||
.collect(Collectors.toMap(pair -> pair.getFirst().toString().replace(idPrefix, StringUtils.EMPTY), Pair::getSecond));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path for a given category in human-readable form.
|
||||
*
|
||||
* @param category Category to provide path for.
|
||||
* @return Path for a category in human-readable form.
|
||||
*/
|
||||
private String getCategoryPath(final Category category)
|
||||
{
|
||||
final NodeRef categoryNodeRef = nodes.getNode(category.getId()).getNodeRef();
|
||||
return nodeService.getPath(categoryNodeRef).toDisplayPath(nodeService, permissionService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1356,7 +1356,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
private void calculateRelativePath(String parentFolderNodeId, Node node)
|
||||
{
|
||||
NodeRef rootNodeRef = validateOrLookupNode(parentFolderNodeId);
|
||||
NodeRef rootNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
||||
try
|
||||
{
|
||||
// get the path elements
|
||||
@@ -1741,7 +1741,7 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public void deleteNode(String nodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId);
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
@@ -1785,7 +1785,7 @@ public class NodesImpl implements Nodes
|
||||
validateProperties(nodeInfo.getProperties(), EXCLUDED_NS, Arrays.asList());
|
||||
|
||||
// check that requested parent node exists and it's type is a (sub-)type of folder
|
||||
NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId);
|
||||
NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
||||
|
||||
// node name - mandatory
|
||||
String nodeName = nodeInfo.getName();
|
||||
@@ -2290,7 +2290,7 @@ public class NodesImpl implements Nodes
|
||||
validateAspects(nodeInfo.getAspectNames(), EXCLUDED_NS, EXCLUDED_ASPECTS);
|
||||
validateProperties(nodeInfo.getProperties(), EXCLUDED_NS, Arrays.asList());
|
||||
|
||||
final NodeRef nodeRef = validateOrLookupNode(nodeId);
|
||||
final NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
QName nodeTypeQName = getNodeType(nodeRef);
|
||||
|
||||
@@ -2523,8 +2523,8 @@ public class NodesImpl implements Nodes
|
||||
throw new InvalidArgumentException("Missing targetParentId");
|
||||
}
|
||||
|
||||
final NodeRef parentNodeRef = validateOrLookupNode(targetParentId);
|
||||
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId);
|
||||
final NodeRef parentNodeRef = validateOrLookupNode(targetParentId, null);
|
||||
final NodeRef sourceNodeRef = validateOrLookupNode(sourceNodeId, null);
|
||||
|
||||
FileInfo fi = moveOrCopyImpl(sourceNodeRef, parentNodeRef, name, isCopy);
|
||||
return getFolderOrDocument(fi.getNodeRef().getId(), parameters);
|
||||
@@ -2954,7 +2954,7 @@ public class NodesImpl implements Nodes
|
||||
throw new InvalidArgumentException("The request content-type is not multipart: "+parentFolderNodeId);
|
||||
}
|
||||
|
||||
NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId);
|
||||
NodeRef parentNodeRef = validateOrLookupNode(parentFolderNodeId, null);
|
||||
if (!nodeMatches(parentNodeRef, Collections.singleton(ContentModel.TYPE_FOLDER), null, false))
|
||||
{
|
||||
throw new InvalidArgumentException("NodeId of folder is expected: " + parentNodeRef.getId());
|
||||
@@ -3385,7 +3385,7 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node lock(String nodeId, LockInfo lockInfo, Parameters parameters)
|
||||
{
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId);
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
@@ -3424,7 +3424,7 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node unlock(String nodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId);
|
||||
NodeRef nodeRef = validateOrLookupNode(nodeId, null);
|
||||
|
||||
if (isSpecialNode(nodeRef, getNodeType(nodeRef)))
|
||||
{
|
||||
|
||||
@@ -185,7 +185,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
||||
String rootNodeId = parameters.getParameter(PARAM_ROOT_NODE_ID);
|
||||
if (rootNodeId != null)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(rootNodeId);
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(rootNodeId, null);
|
||||
query.append("PATH:\"").append(getQNamePath(nodeRef.getId())).append("//*\" AND (");
|
||||
}
|
||||
if (term != null)
|
||||
|
||||
@@ -695,7 +695,7 @@ public class RenditionsImpl implements Renditions, ResourceLoaderAware
|
||||
{
|
||||
if (versionLabelId != null)
|
||||
{
|
||||
nodeRef = nodes.validateOrLookupNode(nodeRef.getId());
|
||||
nodeRef = nodes.validateOrLookupNode(nodeRef.getId(), null);
|
||||
VersionHistory vh = versionService.getVersionHistory(nodeRef);
|
||||
if (vh != null)
|
||||
{
|
||||
|
||||
@@ -25,26 +25,16 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.EQUALS;
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.IN;
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.MATCHES;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.alfresco.service.cmr.tagging.TaggingService.TAG_ROOT_NODE_REF;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.ListBackedPagingResults;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
@@ -61,11 +51,8 @@ import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationE
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.Query;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryImpl;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
@@ -81,266 +68,227 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
public static final String PARAM_INCLUDE_COUNT = "count";
|
||||
private static final String PARAM_WHERE_TAG = "tag";
|
||||
static final String NOT_A_VALID_TAG = "An invalid parameter has been supplied";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_TAG = "Current user does not have permission to manage a tag";
|
||||
private static final Object PARAM_INCLUDE_COUNT = "count";
|
||||
static final String NOT_A_VALID_TAG = "An invalid parameter has been supplied";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_TAG = "Current user does not have permission to manage a tag";
|
||||
|
||||
private Nodes nodes;
|
||||
private NodeService nodeService;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
private AuthorityService authorityService;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
private AuthorityService authorityService;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
if (!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
if(!typeConstraint.matches(nodeRef))
|
||||
{
|
||||
throw new UnsupportedResourceOperationException("Cannot tag this node");
|
||||
}
|
||||
|
||||
List<String> tagValues = tags.stream().map(Tag::getTag).collect(toList());
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<>(tags.size());
|
||||
List<Pair<String, Integer>> tagsCountPairList = taggingService.findTaggedNodesAndCountByTagName(nodeRef.getStoreRef());
|
||||
Map<String, Long> tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst, pair -> Long.valueOf(pair.getSecond())));
|
||||
for (Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
List<String> tagValues = new AbstractList<String>()
|
||||
{
|
||||
Tag createdTag = new Tag(pair.getSecond(), pair.getFirst());
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
@Override
|
||||
public String get(int arg0)
|
||||
{
|
||||
createdTag.setCount(Optional.ofNullable(tagsCountMap.get(createdTag.getTag())).orElse(0L) + 1);
|
||||
String tag = tags.get(arg0).getTag();
|
||||
return tag;
|
||||
}
|
||||
ret.add(createdTag);
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return tags.size();
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<Tag>(tags.size());
|
||||
for(Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
ret.add(new Tag(pair.getSecond(), pair.getFirst()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(STORE_REF_WORKSPACE_SPACESSTORE, tagId, null);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(tagId);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTagById(StoreRef storeRef, String tagId) {
|
||||
verifyAdminAuthority();
|
||||
public void deleteTagById(StoreRef storeRef, String tagId) {
|
||||
verifyAdminAuthority();
|
||||
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
taggingService.deleteTag(storeRef, tagValue);
|
||||
}
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
taggingService.deleteTag(storeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params)
|
||||
{
|
||||
Paging paging = params.getPaging();
|
||||
Pair<String, Boolean> sorting = !params.getSorting().isEmpty() ? new Pair<>(params.getSorting().get(0).column, params.getSorting().get(0).asc) : null;
|
||||
Map<Integer, Collection<String>> namesFilters = resolveTagNamesQuery(params.getQuery());
|
||||
|
||||
Map<NodeRef, Long> results = taggingService.getTags(storeRef, params.getInclude(), sorting, namesFilters.get(EQUALS), namesFilters.get(MATCHES));
|
||||
|
||||
List<Tag> tagsList = results.entrySet().stream().map(entry -> new Tag(entry.getKey(), (String)nodeService.getProperty(entry.getKey(), ContentModel.PROP_NAME))).collect(Collectors.toList());
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging));
|
||||
taggingService.getPagedTags(storeRef, 0, paging.getMaxItems());
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
List<Pair<String, Integer>> tagsByCount = null;
|
||||
Map<String, Integer> tagsByCountMap = new HashMap<String, Integer>();
|
||||
|
||||
if (params.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tagsList.forEach(tag -> tag.setCount(results.get(tag.getNodeRef())));
|
||||
tagsByCount = taggingService.findTaggedNodesAndCountByTagName(storeRef);
|
||||
if (tagsByCount != null)
|
||||
{
|
||||
for (Pair<String, Integer> tagByCountElem : tagsByCount)
|
||||
{
|
||||
tagsByCountMap.put(tagByCountElem.getFirst(), tagByCountElem.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
Tag selectedTag = new Tag(pair.getFirst(), pair.getSecond());
|
||||
selectedTag.setCount(Optional.ofNullable(tagsByCountMap.get(selectedTag.getTag())).orElse(0));
|
||||
tags.add(selectedTag);
|
||||
}
|
||||
|
||||
ListBackedPagingResults listBackedPagingResults = new ListBackedPagingResults(tagsList, Util.getPagingRequest(params.getPaging()));
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, listBackedPagingResults.getPage(), listBackedPagingResults.hasMoreItems(), (Integer) listBackedPagingResults.getTotalResultCount().getFirst());
|
||||
return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
if(tagNodeRef == null)
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the number of times the given tag is used (if requested).
|
||||
*
|
||||
* @param storeRef The store the tag is in.
|
||||
* @param tagName The name of the tag.
|
||||
* @param parameters The request parameters object containing the includes parameter.
|
||||
* @return The number of times the tag is applied, or null if "count" wasn't in the include parameter.
|
||||
*/
|
||||
private Long findCountIfRequested(StoreRef storeRef, String tagName, Parameters parameters)
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag)
|
||||
{
|
||||
Long count = null;
|
||||
if (parameters != null && parameters.getInclude() != null && parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
count = taggingService.findCountByTagName(storeRef, tagName);
|
||||
}
|
||||
return count;
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return new Tag(newTagNodeRef, newTagName);
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag, Parameters parameters)
|
||||
public Tag getTag(String tagId)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, existingTagName, parameters);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return Tag.builder().nodeRef(newTagNodeRef).tag(newTagName).count(count).create();
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getTag(StoreRef storeRef, String tagId, Parameters parameters)
|
||||
public Tag getTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagName = taggingService.getTagName(tagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, tagName, parameters);
|
||||
return Tag.builder().nodeRef(tagNodeRef).tag(tagName).count(count).create();
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
return new Tag(tagNodeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Tag> getTags(String nodeId, Parameters params)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
NodeRef nodeRef = validateTag(nodeId);
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(nodeRef, Util.getPagingRequest(params.getPaging()));
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<Tag>(page.size());
|
||||
for(Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
tags.add(new Tag(pair.getFirst(), pair.getSecond()));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> createTags(final StoreRef storeRef, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final List<String> tagNames = Optional.ofNullable(tags).orElse(Collections.emptyList()).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Tag::getTag)
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
@Experimental
|
||||
@Override
|
||||
public List<Tag> createTags(final StoreRef storeRef, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final List<String> tagNames = Optional.ofNullable(tags).orElse(Collections.emptyList()).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Tag::getTag)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(tagNames))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_TAG);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(tagNames))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
return taggingService.createTags(storeRef, tagNames).stream()
|
||||
.map(pair -> Tag.builder().tag(pair.getFirst()).nodeRef(pair.getSecond()).create())
|
||||
.peek(tag -> {
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tag.setCount(0L);
|
||||
}
|
||||
}).collect(toList());
|
||||
}
|
||||
return taggingService.createTags(storeRef, tagNames).stream()
|
||||
.map(pair -> Tag.builder().tag(pair.getFirst()).nodeRef(pair.getSecond()).create())
|
||||
.peek(tag -> {
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tag.setCount(0);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void verifyAdminAuthority()
|
||||
{
|
||||
if (!authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new PermissionDeniedException(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method resolves where query looking for clauses: EQUALS, IN or MATCHES.
|
||||
* Expected values for EQUALS and IN will be merged under EQUALS clause.
|
||||
* @param namesQuery Where query with expected tag name(s).
|
||||
* @return Map of expected exact and alike tag names.
|
||||
*/
|
||||
private Map<Integer, Collection<String>> resolveTagNamesQuery(final Query namesQuery)
|
||||
{
|
||||
if (namesQuery == null || namesQuery == QueryImpl.EMPTY)
|
||||
{
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<Integer, Collection<String>> properties = QueryHelper
|
||||
.resolve(namesQuery)
|
||||
.usingOrOperator()
|
||||
.withoutNegations()
|
||||
.getProperty(PARAM_WHERE_TAG)
|
||||
.getExpectedValuesForAnyOf(EQUALS, IN, MATCHES)
|
||||
.skipNegated();
|
||||
|
||||
return properties.entrySet().stream()
|
||||
.collect(Collectors.groupingBy((entry) -> {
|
||||
if (entry.getKey() == EQUALS || entry.getKey() == IN)
|
||||
{
|
||||
return EQUALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MATCHES;
|
||||
}
|
||||
}, Collectors.flatMapping((entry) -> entry.getValue().stream().map(String::toLowerCase), Collectors.toCollection(HashSet::new))));
|
||||
}
|
||||
|
||||
private NodeRef checkTagRootAsNodePrimaryParent(String tagId, NodeRef tagNodeRef)
|
||||
{
|
||||
if ( tagNodeRef == null || !nodeService.getPrimaryParent(tagNodeRef).getParentRef().equals(TAG_ROOT_NODE_REF))
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
private void verifyAdminAuthority()
|
||||
{
|
||||
if (!authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new PermissionDeniedException(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class RestRuleModelMapper implements RestModelMapper<Rule, org.alfresco.s
|
||||
public org.alfresco.service.cmr.rule.Rule toServiceModel(Rule restRuleModel)
|
||||
{
|
||||
final org.alfresco.service.cmr.rule.Rule serviceRule = new org.alfresco.service.cmr.rule.Rule();
|
||||
final NodeRef nodeRef = (restRuleModel.getId() != null) ? nodes.validateOrLookupNode(restRuleModel.getId()) : null;
|
||||
final NodeRef nodeRef = (restRuleModel.getId() != null) ? nodes.validateOrLookupNode(restRuleModel.getId(), null) : null;
|
||||
serviceRule.setNodeRef(nodeRef);
|
||||
serviceRule.setTitle(restRuleModel.getName());
|
||||
serviceRule.setDescription(restRuleModel.getDescription());
|
||||
|
||||
@@ -129,7 +129,7 @@ public class RestRuleSimpleConditionModelMapper implements RestModelMapper<Simpl
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_ASPECT, ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
try
|
||||
{
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, nodes.validateOrLookupNode(parameter));
|
||||
parameterValues.put(InCategoryEvaluator.PARAM_CATEGORY_VALUE, nodes.validateOrLookupNode(parameter, null));
|
||||
} catch (EntityNotFoundException e) {
|
||||
throw new InvalidArgumentException(CATEGORY_INVALID_MSG);
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ public class ActionParameterConverter
|
||||
}
|
||||
else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(stringValue);
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(stringValue, null);
|
||||
if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
|
||||
{
|
||||
throw new EntityNotFoundException(stringValue);
|
||||
|
||||
@@ -72,7 +72,7 @@ public class NodeValidator
|
||||
{
|
||||
try
|
||||
{
|
||||
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId);
|
||||
final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
|
||||
validatePermission(requireChangePermission, nodeRef);
|
||||
verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ public class Category
|
||||
private String parentId;
|
||||
private boolean hasChildren;
|
||||
private Integer count;
|
||||
private String path;
|
||||
|
||||
public String getId()
|
||||
{
|
||||
@@ -92,14 +91,6 @@ public class Category
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
@@ -109,20 +100,19 @@ public class Category
|
||||
return false;
|
||||
Category category = (Category) o;
|
||||
return hasChildren == category.hasChildren && Objects.equals(id, category.id) && Objects.equals(name, category.name) && Objects.equals(parentId, category.parentId)
|
||||
&& Objects.equals(count, category.count) && Objects.equals(path, category.path);
|
||||
&& Objects.equals(count, category.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(id, name, parentId, hasChildren, count, path);
|
||||
return Objects.hash(id, name, parentId, hasChildren, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Category{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", parentId='" + parentId + '\'' + ", hasChildren=" + hasChildren
|
||||
+ ", count=" + count + ", path=" + path + '}';
|
||||
return "Category{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", parentId='" + parentId + '\'' + ", hasChildren=" + hasChildren + ", count=" + count + '}';
|
||||
}
|
||||
|
||||
public static Builder builder()
|
||||
@@ -137,7 +127,6 @@ public class Category
|
||||
private String parentId;
|
||||
private boolean hasChildren;
|
||||
private Integer count;
|
||||
private String path;
|
||||
|
||||
public Builder id(String id)
|
||||
{
|
||||
@@ -169,12 +158,6 @@ public class Category
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder path(String path)
|
||||
{
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Category create()
|
||||
{
|
||||
final Category category = new Category();
|
||||
@@ -183,7 +166,6 @@ public class Category
|
||||
category.setParentId(parentId);
|
||||
category.setHasChildren(hasChildren);
|
||||
category.setCount(count);
|
||||
category.setPath(path);
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package org.alfresco.rest.api.model;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.alfresco.rest.framework.resource.UniqueId;
|
||||
@@ -42,7 +41,7 @@ public class Tag implements Comparable<Tag>
|
||||
{
|
||||
private NodeRef nodeRef;
|
||||
private String tag;
|
||||
private Long count;
|
||||
private Integer count;
|
||||
|
||||
public Tag()
|
||||
{
|
||||
@@ -51,7 +50,7 @@ public class Tag implements Comparable<Tag>
|
||||
public Tag(NodeRef nodeRef, String tag)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
setTag(tag);
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
@@ -73,16 +72,16 @@ public class Tag implements Comparable<Tag>
|
||||
|
||||
public void setTag(String tag)
|
||||
{
|
||||
this.tag = Optional.ofNullable(tag).map(String::toLowerCase).orElse(null);
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public Long getCount()
|
||||
public Integer getCount()
|
||||
{
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(Long count)
|
||||
public void setCount(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
}
|
||||
@@ -101,21 +100,37 @@ public class Tag implements Comparable<Tag>
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Tag tag1 = (Tag) o;
|
||||
return Objects.equals(nodeRef, tag1.nodeRef) && Objects.equals(tag, tag1.tag) && Objects.equals(count, tag1.count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(nodeRef, tag, count);
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((nodeRef == null) ? 0 : nodeRef.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tags are equal if they have the same NodeRef
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Tag other = (Tag) obj;
|
||||
if (nodeRef == null) {
|
||||
if (other.nodeRef != null)
|
||||
return false;
|
||||
} else if (!nodeRef.equals(other.nodeRef))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +148,7 @@ public class Tag implements Comparable<Tag>
|
||||
{
|
||||
private NodeRef nodeRef;
|
||||
private String tag;
|
||||
private Long count;
|
||||
private Integer count;
|
||||
|
||||
public Builder nodeRef(NodeRef nodeRef)
|
||||
{
|
||||
@@ -147,7 +162,7 @@ public class Tag implements Comparable<Tag>
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder count(Long count)
|
||||
public Builder count(Integer count)
|
||||
{
|
||||
this.count = count;
|
||||
return this;
|
||||
|
||||
@@ -31,9 +31,13 @@ import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.SortColumn;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RelationshipResource(name = "action-definitions", entityResource = NodesEntityResource.class, title = "Node action definitions")
|
||||
public class NodeActionDefinitionsRelation extends AbstractNodeRelation
|
||||
implements RelationshipResourceAction.Read<ActionDefinition>
|
||||
@@ -55,7 +59,7 @@ public class NodeActionDefinitionsRelation extends AbstractNodeRelation
|
||||
@Override
|
||||
public CollectionWithPagingInfo<ActionDefinition> readAll(String entityResourceId, Parameters params)
|
||||
{
|
||||
NodeRef parentNodeRef = nodes.validateOrLookupNode(entityResourceId);
|
||||
NodeRef parentNodeRef = nodes.validateOrLookupNode(entityResourceId, null);
|
||||
return actions.getActionDefinitions(parentNodeRef, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
@@ -46,6 +41,11 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Node Parents
|
||||
*
|
||||
@@ -67,7 +67,7 @@ public class NodeParentsRelation extends AbstractNodeRelation implements Relatio
|
||||
@WebApiDescription(title = "Return a list of parent nodes based on child assocs")
|
||||
public CollectionWithPagingInfo<Node> readAll(String childNodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef childNodeRef = nodes.validateOrLookupNode(childNodeId);
|
||||
NodeRef childNodeRef = nodes.validateOrLookupNode(childNodeId, null);
|
||||
|
||||
QNamePattern assocTypeQNameParam = RegexQNamePattern.MATCH_ALL;
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.AssocChild;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
@@ -43,6 +41,8 @@ import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Node Secondary Children
|
||||
*
|
||||
@@ -71,7 +71,7 @@ public class NodeSecondaryChildrenRelation extends AbstractNodeRelation implemen
|
||||
@WebApiDescription(title = "Return a paged list of secondary child nodes based on child assocs")
|
||||
public CollectionWithPagingInfo<Node> readAll(String parentNodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef parentNodeRef = nodes.validateOrLookupNode(parentNodeId);
|
||||
NodeRef parentNodeRef = nodes.validateOrLookupNode(parentNodeId, null);
|
||||
|
||||
QNamePattern assocTypeQNameParam = getAssocTypeFromWhereElseAll(parameters);
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
@@ -37,6 +35,8 @@ import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Node Sources - list node (peer) associations from target to sources
|
||||
*
|
||||
@@ -54,7 +54,7 @@ public class NodeSourcesRelation extends AbstractNodeRelation implements Relatio
|
||||
@WebApiDescription(title = "Return a paged list of sources nodes based on (peer) assocs")
|
||||
public CollectionWithPagingInfo<Node> readAll(String targetNodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef targetNodeRef = nodes.validateOrLookupNode(targetNodeId);
|
||||
NodeRef targetNodeRef = nodes.validateOrLookupNode(targetNodeId, null);
|
||||
|
||||
QNamePattern assocTypeQNameParam = getAssocTypeFromWhereElseAll(parameters);
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.util.List;
|
||||
@@ -61,7 +61,7 @@ public class NodeTagsRelation implements RelationshipResourceAction.Create<Tag>,
|
||||
@WebApiDescription(title="Adds one or more tags to the node with id 'nodeId'.")
|
||||
public List<Tag> create(String nodeId, List<Tag> tagsToCreate, Parameters parameters)
|
||||
{
|
||||
return tags.addTags(nodeId, tagsToCreate, parameters);
|
||||
return tags.addTags(nodeId, tagsToCreate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.AssocTarget;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
@@ -42,6 +40,8 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QNamePattern;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Node Targets
|
||||
*
|
||||
@@ -64,7 +64,7 @@ public class NodeTargetsRelation extends AbstractNodeRelation implements
|
||||
@WebApiDescription(title = "Return a paged list of target nodes based on (peer) assocs")
|
||||
public CollectionWithPagingInfo<Node> readAll(String sourceNodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef sourceNodeRef = nodes.validateOrLookupNode(sourceNodeId);
|
||||
NodeRef sourceNodeRef = nodes.validateOrLookupNode(sourceNodeId, null);
|
||||
|
||||
QNamePattern assocTypeQNameParam = getAssocTypeFromWhereElseAll(parameters);
|
||||
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.nodes;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
|
||||
import org.alfresco.repo.node.integrity.IntegrityException;
|
||||
@@ -72,6 +65,13 @@ import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Node Versions - version history
|
||||
*
|
||||
@@ -117,7 +117,7 @@ public class NodeVersionsRelation extends AbstractNodeRelation implements
|
||||
@WebApiDescription(title = "Return version history as a paged list of version node infos")
|
||||
public CollectionWithPagingInfo<Node> readAll(String nodeId, Parameters parameters)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId, null);
|
||||
|
||||
VersionHistory vh = versionService.getVersionHistory(nodeRef);
|
||||
|
||||
@@ -293,7 +293,7 @@ public class NodeVersionsRelation extends AbstractNodeRelation implements
|
||||
|
||||
public Version findVersion(String nodeId, String versionLabelId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId);
|
||||
NodeRef nodeRef = nodes.validateOrLookupNode(nodeId, null);
|
||||
VersionHistory vh = versionService.getVersionHistory(nodeRef);
|
||||
if (vh != null)
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.tags;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.api.Tags;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
@@ -36,6 +36,7 @@ import org.alfresco.rest.framework.resource.EntityResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||
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.StoreRef;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -58,8 +59,9 @@ public class TagsEntityResource implements EntityResourceAction.Read<Tag>,
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns a paged list of all currently used tags in the store workspace://SpacesStore for the current tenant.
|
||||
* GET /tags
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
@WebApiDescription(title="A paged list of all tags in the network.")
|
||||
@@ -72,18 +74,19 @@ public class TagsEntityResource implements EntityResourceAction.Read<Tag>,
|
||||
@WebApiDescription(title="Updates a tag by unique Id")
|
||||
public Tag update(String id, Tag entity, Parameters parameters)
|
||||
{
|
||||
return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity, parameters);
|
||||
return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag readById(String id, Parameters parameters) throws EntityNotFoundException
|
||||
{
|
||||
return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, parameters);
|
||||
return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /tags
|
||||
*/
|
||||
@Experimental
|
||||
@WebApiDescription(
|
||||
title = "Create an orphan tag",
|
||||
description = "Creates a tag, which is not associated with any node",
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 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.framework.resource.parameters.where;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* Basic implementation of {@link QueryHelper.WalkerCallbackAdapter} providing universal handling of Where query clauses.
|
||||
* This implementation supports AND operator and all clause types.
|
||||
* Be default, walker verifies strictly if expected or unexpected properties, and it's comparison types are present in query
|
||||
* and throws {@link InvalidQueryException} if they are missing.
|
||||
*/
|
||||
public class BasicQueryWalker extends QueryHelper.WalkerCallbackAdapter
|
||||
{
|
||||
private static final String EQUALS_AND_IN_NOT_ALLOWED_TOGETHER = "Where query error: cannot use '=' (EQUALS) AND 'IN' clauses with same property: %s";
|
||||
private static final String MISSING_PROPERTY = "Where query error: property with name: %s not present";
|
||||
static final String MISSING_CLAUSE_TYPE = "Where query error: property with name: %s expects clause: %s";
|
||||
static final String MISSING_ANY_CLAUSE_OF_TYPE = "Where query error: property with name: %s expects at least one of clauses: %s";
|
||||
private static final String PROPERTY_NOT_EXPECTED = "Where query error: property with name: %s is not expected";
|
||||
private static final String PROPERTY_NOT_NEGATABLE = "Where query error: property with name: %s cannot be negated";
|
||||
private static final String PROPERTY_NAMES_EMPTY = "Cannot verify WHERE query without expected property names";
|
||||
|
||||
private Collection<String> expectedPropertyNames;
|
||||
private final Map<String, WhereProperty> properties;
|
||||
protected boolean clausesNegatable = true;
|
||||
protected boolean validateStrictly = true;
|
||||
|
||||
public BasicQueryWalker()
|
||||
{
|
||||
this.properties = new HashMap<>();
|
||||
}
|
||||
|
||||
public BasicQueryWalker(final String... expectedPropertyNames)
|
||||
{
|
||||
this();
|
||||
this.expectedPropertyNames = Set.of(expectedPropertyNames);
|
||||
}
|
||||
|
||||
public BasicQueryWalker(final Collection<String> expectedPropertyNames)
|
||||
{
|
||||
this();
|
||||
this.expectedPropertyNames = expectedPropertyNames;
|
||||
}
|
||||
|
||||
public void setClausesNegatable(final boolean clausesNegatable)
|
||||
{
|
||||
this.clausesNegatable = clausesNegatable;
|
||||
}
|
||||
|
||||
public void setValidateStrictly(boolean validateStrictly)
|
||||
{
|
||||
this.validateStrictly = validateStrictly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exists(String propertyName, boolean negated)
|
||||
{
|
||||
verifyPropertyExpectedness(propertyName);
|
||||
verifyClausesNegatability(negated, propertyName);
|
||||
addProperties(propertyName, WhereClauseParser.EXISTS, negated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void between(String propertyName, String firstValue, String secondValue, boolean negated)
|
||||
{
|
||||
verifyPropertyExpectedness(propertyName);
|
||||
verifyClausesNegatability(negated, propertyName);
|
||||
addProperties(propertyName, WhereClauseParser.BETWEEN, negated, firstValue, secondValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comparison(int type, String propertyName, String propertyValue, boolean negated)
|
||||
{
|
||||
verifyPropertyExpectedness(propertyName);
|
||||
verifyClausesNegatability(negated, propertyName);
|
||||
if (WhereClauseParser.EQUALS == type && isAndSupported() && containsProperty(propertyName, WhereClauseParser.IN, negated))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(EQUALS_AND_IN_NOT_ALLOWED_TOGETHER, propertyName));
|
||||
}
|
||||
|
||||
addProperties(propertyName, type, negated, propertyValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void in(String propertyName, boolean negated, String... propertyValues)
|
||||
{
|
||||
verifyPropertyExpectedness(propertyName);
|
||||
verifyClausesNegatability(negated, propertyName);
|
||||
if (isAndSupported() && containsProperty(propertyName, WhereClauseParser.EQUALS, negated))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(EQUALS_AND_IN_NOT_ALLOWED_TOGETHER, propertyName));
|
||||
}
|
||||
|
||||
addProperties(propertyName, WhereClauseParser.IN, negated, propertyValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void matches(final String propertyName, String propertyValue, boolean negated)
|
||||
{
|
||||
verifyPropertyExpectedness(propertyName);
|
||||
verifyClausesNegatability(negated, propertyName);
|
||||
addProperties(propertyName, WhereClauseParser.MATCHES, negated, propertyValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void and()
|
||||
{
|
||||
// Don't need to do anything here - it's enough to enable AND operator.
|
||||
// OR is not supported at the same time.
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if property is expected, if not throws {@link InvalidQueryException}.
|
||||
*/
|
||||
protected void verifyPropertyExpectedness(final String propertyName)
|
||||
{
|
||||
if (validateStrictly && CollectionUtils.isNotEmpty(expectedPropertyNames) && !this.expectedPropertyNames.contains(propertyName))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(PROPERTY_NOT_EXPECTED, propertyName));
|
||||
}
|
||||
else if (validateStrictly && CollectionUtils.isEmpty(expectedPropertyNames))
|
||||
{
|
||||
throw new IllegalStateException(PROPERTY_NAMES_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if clause negations are allowed, if not throws {@link InvalidQueryException}.
|
||||
*/
|
||||
protected void verifyClausesNegatability(final boolean negated, final String propertyName)
|
||||
{
|
||||
if (!clausesNegatable && negated)
|
||||
{
|
||||
throw new InvalidQueryException(String.format(PROPERTY_NOT_NEGATABLE, propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAndSupported()
|
||||
{
|
||||
try
|
||||
{
|
||||
and();
|
||||
return true;
|
||||
}
|
||||
catch (InvalidQueryException ignore)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void addProperties(final String propertyName, final int clauseType, final String... propertyValues)
|
||||
{
|
||||
this.addProperties(propertyName, clauseType, false, propertyValues);
|
||||
}
|
||||
|
||||
protected void addProperties(final String propertyName, final int clauseType, final boolean negated, final String... propertyValues)
|
||||
{
|
||||
final WhereProperty.ClauseType type = WhereProperty.ClauseType.of(clauseType, negated);
|
||||
final Set<String> propertiesToAdd = Optional.ofNullable(propertyValues).map(Set::of).orElse(Collections.emptySet());
|
||||
if (this.containsProperty(propertyName))
|
||||
{
|
||||
this.properties.get(propertyName).addValuesToType(type, propertiesToAdd);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.properties.put(propertyName, new WhereProperty(propertyName, type, propertiesToAdd, validateStrictly));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean containsProperty(final String propertyName)
|
||||
{
|
||||
return this.properties.containsKey(propertyName);
|
||||
}
|
||||
|
||||
protected boolean containsProperty(final String propertyName, final int clauseType, final boolean negated)
|
||||
{
|
||||
return this.properties.containsKey(propertyName) && this.properties.get(propertyName).containsType(clauseType, negated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getProperty(String propertyName, int type, boolean negated)
|
||||
{
|
||||
return this.getProperty(propertyName).getExpectedValuesFor(type, negated);
|
||||
}
|
||||
|
||||
public WhereProperty getProperty(final String propertyName)
|
||||
{
|
||||
if (validateStrictly && !this.containsProperty(propertyName))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_PROPERTY, propertyName));
|
||||
}
|
||||
|
||||
return this.properties.get(propertyName);
|
||||
}
|
||||
|
||||
public List<WhereProperty> getProperties(final String... propertyNames)
|
||||
{
|
||||
return Arrays.stream(propertyNames)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.peek(propertyName -> {
|
||||
if (validateStrictly && !this.containsProperty(propertyName))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_PROPERTY, propertyName));
|
||||
}
|
||||
})
|
||||
.map(this.properties::get)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Map<String, WhereProperty> getPropertiesAsMap(final String... propertyNames)
|
||||
{
|
||||
return Arrays.stream(propertyNames)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.peek(propertyName -> {
|
||||
if (validateStrictly && !this.containsProperty(propertyName))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_PROPERTY, propertyName));
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toMap(propertyName -> propertyName, this.properties::get));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -25,19 +25,10 @@
|
||||
*/
|
||||
package org.alfresco.rest.framework.resource.parameters.where;
|
||||
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.BETWEEN;
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.EQUALS;
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.EXISTS;
|
||||
import static org.alfresco.rest.antlr.WhereClauseParser.IN;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.antlr.runtime.tree.CommonTree;
|
||||
@@ -54,19 +45,14 @@ public abstract class QueryHelper
|
||||
/**
|
||||
* An interface used when walking a query tree. Calls are made to methods when the particular clause is encountered.
|
||||
*/
|
||||
public interface WalkerCallback
|
||||
public static interface WalkerCallback
|
||||
{
|
||||
InvalidQueryException UNSUPPORTED = new InvalidQueryException("Unsupported Predicate");
|
||||
|
||||
/**
|
||||
* Called any time an EXISTS clause is encountered.
|
||||
* @param propertyName Name of the property
|
||||
* @param negated returns true if "NOT EXISTS" was used
|
||||
*/
|
||||
default void exists(String propertyName, boolean negated)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
void exists(String propertyName, boolean negated);
|
||||
|
||||
/**
|
||||
* Called any time a BETWEEN clause is encountered.
|
||||
@@ -75,18 +61,12 @@ public abstract class QueryHelper
|
||||
* @param secondValue String
|
||||
* @param negated returns true if "NOT BETWEEN" was used
|
||||
*/
|
||||
default void between(String propertyName, String firstValue, String secondValue, boolean negated)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
void between(String propertyName, String firstValue, String secondValue, boolean negated);
|
||||
|
||||
/**
|
||||
* One of EQUALS LESSTHAN GREATERTHAN LESSTHANOREQUALS GREATERTHANOREQUALS;
|
||||
*/
|
||||
default void comparison(int type, String propertyName, String propertyValue, boolean negated)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
void comparison(int type, String propertyName, String propertyValue, boolean negated);
|
||||
|
||||
/**
|
||||
* Called any time an IN clause is encountered.
|
||||
@@ -94,10 +74,7 @@ public abstract class QueryHelper
|
||||
* @param negated returns true if "NOT IN" was used
|
||||
* @param propertyValues the property values
|
||||
*/
|
||||
default void in(String property, boolean negated, String... propertyValues)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
void in(String property, boolean negated, String... propertyValues);
|
||||
|
||||
/**
|
||||
* Called any time a MATCHES clause is encountered.
|
||||
@@ -105,37 +82,42 @@ public abstract class QueryHelper
|
||||
* @param propertyValue String
|
||||
* @param negated returns true if "NOT MATCHES" was used
|
||||
*/
|
||||
default void matches(String property, String propertyValue, boolean negated)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
void matches(String property, String propertyValue, boolean negated);
|
||||
|
||||
/**
|
||||
* Called any time an AND is encountered.
|
||||
*/
|
||||
default void and()
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
*/
|
||||
void and();
|
||||
/**
|
||||
* Called any time an OR is encountered.
|
||||
*/
|
||||
default void or()
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
|
||||
default Collection<String> getProperty(String propertyName, int type, boolean negated)
|
||||
{
|
||||
throw UNSUPPORTED;
|
||||
}
|
||||
*/
|
||||
void or();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation. Override the methods you are interested in. If you don't
|
||||
* override the methods then an InvalidQueryException will be thrown.
|
||||
*/
|
||||
public static class WalkerCallbackAdapter implements WalkerCallback {}
|
||||
public static class WalkerCallbackAdapter implements WalkerCallback
|
||||
{
|
||||
private static final String UNSUPPORTED_TEXT = "Unsupported Predicate";
|
||||
protected static final InvalidQueryException UNSUPPORTED = new InvalidQueryException(UNSUPPORTED_TEXT);
|
||||
|
||||
@Override
|
||||
public void exists(String propertyName, boolean negated) { throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void between(String propertyName, String firstValue, String secondValue, boolean negated) { throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void comparison(int type, String propertyName, String propertyValue, boolean negated) { throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void in(String propertyName, boolean negated, String... propertyValues) { throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void matches(String property, String value, boolean negated) { throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void and() {throw UNSUPPORTED;}
|
||||
@Override
|
||||
public void or() {throw UNSUPPORTED;}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks a query with a callback for each operation
|
||||
@@ -164,7 +146,7 @@ public abstract class QueryHelper
|
||||
if (tree != null)
|
||||
{
|
||||
switch (tree.getType()) {
|
||||
case EXISTS:
|
||||
case WhereClauseParser.EXISTS:
|
||||
if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType())
|
||||
{
|
||||
callback.exists(tree.getChild(0).getText(), negated);
|
||||
@@ -178,7 +160,7 @@ public abstract class QueryHelper
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case IN:
|
||||
case WhereClauseParser.IN:
|
||||
if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType())
|
||||
{
|
||||
List<Tree> children = getChildren(tree);
|
||||
@@ -192,14 +174,14 @@ public abstract class QueryHelper
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case BETWEEN:
|
||||
case WhereClauseParser.BETWEEN:
|
||||
if (WhereClauseParser.PROPERTYNAME == tree.getChild(0).getType())
|
||||
{
|
||||
callback.between(tree.getChild(0).getText(), stripQuotes(tree.getChild(1).getText()), stripQuotes(tree.getChild(2).getText()), negated);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EQUALS: //fall through (comparison)
|
||||
case WhereClauseParser.EQUALS: //fall through (comparison)
|
||||
case WhereClauseParser.LESSTHAN: //fall through (comparison)
|
||||
case WhereClauseParser.GREATERTHAN: //fall through (comparison)
|
||||
case WhereClauseParser.LESSTHANOREQUALS: //fall through (comparison)
|
||||
@@ -304,180 +286,4 @@ public abstract class QueryHelper
|
||||
}
|
||||
return toBeStripped; //default to return the String unchanged.
|
||||
}
|
||||
|
||||
public static QueryResolver.WalkerSpecifier resolve(final Query query)
|
||||
{
|
||||
return new QueryResolver.WalkerSpecifier(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class allowing WHERE query resolving using query walker. By default {@link BasicQueryWalker} is used, but different walker can be supplied.
|
||||
*/
|
||||
public static abstract class QueryResolver<S extends QueryResolver<?>>
|
||||
{
|
||||
private final Query query;
|
||||
protected WalkerCallback queryWalker;
|
||||
protected Function<Collection<String>, BasicQueryWalker> orQueryWalkerSupplier;
|
||||
protected boolean clausesNegatable = true;
|
||||
protected boolean validateLeniently = false;
|
||||
protected abstract S self();
|
||||
|
||||
public QueryResolver(Query query)
|
||||
{
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property expected values.
|
||||
* @param propertyName Property name.
|
||||
* @param clauseType Property comparison type.
|
||||
* @param negated Comparison type negation.
|
||||
* @return Map composed of all comparators and compared values.
|
||||
*/
|
||||
public Collection<String> getProperty(final String propertyName, final int clauseType, final boolean negated)
|
||||
{
|
||||
processQuery(propertyName);
|
||||
return queryWalker.getProperty(propertyName, clauseType, negated);
|
||||
}
|
||||
|
||||
protected void processQuery(final String... propertyNames)
|
||||
{
|
||||
if (queryWalker == null)
|
||||
{
|
||||
if (orQueryWalkerSupplier != null)
|
||||
{
|
||||
queryWalker = orQueryWalkerSupplier.apply(Set.of(propertyNames));
|
||||
}
|
||||
else
|
||||
{
|
||||
queryWalker = new BasicQueryWalker(propertyNames);
|
||||
}
|
||||
}
|
||||
if (queryWalker instanceof BasicQueryWalker)
|
||||
{
|
||||
((BasicQueryWalker) queryWalker).setClausesNegatable(clausesNegatable);
|
||||
((BasicQueryWalker) queryWalker).setValidateStrictly(!validateLeniently);
|
||||
}
|
||||
walk(query, queryWalker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class providing methods related with default query walker {@link BasicQueryWalker}.
|
||||
*/
|
||||
public static class DefaultWalkerOperations<R extends DefaultWalkerOperations<?>> extends QueryResolver<R>
|
||||
{
|
||||
public DefaultWalkerOperations(Query query)
|
||||
{
|
||||
super(query);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected R self()
|
||||
{
|
||||
return (R) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that query properties and comparison types should NOT be verified strictly.
|
||||
*/
|
||||
public R leniently()
|
||||
{
|
||||
this.validateLeniently = true;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that clause types negations are not allowed in query.
|
||||
*/
|
||||
public R withoutNegations()
|
||||
{
|
||||
this.clausesNegatable = false;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property with expected values.
|
||||
* @param propertyName Property name.
|
||||
* @return Map composed of all comparators and compared values.
|
||||
*/
|
||||
public WhereProperty getProperty(final String propertyName)
|
||||
{
|
||||
processQuery(propertyName);
|
||||
return ((BasicQueryWalker) this.queryWalker).getProperty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple properties with it's expected values.
|
||||
* @param propertyNames Property names.
|
||||
* @return List of maps composed of all comparators and compared values.
|
||||
*/
|
||||
public List<WhereProperty> getProperties(final String... propertyNames)
|
||||
{
|
||||
processQuery(propertyNames);
|
||||
return ((BasicQueryWalker) this.queryWalker).getProperties(propertyNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get multiple properties with it's expected values.
|
||||
* @param propertyNames Property names.
|
||||
* @return Map composed of property names and maps composed of all comparators and compared values.
|
||||
*/
|
||||
public Map<String, WhereProperty> getPropertiesAsMap(final String... propertyNames)
|
||||
{
|
||||
processQuery(propertyNames);
|
||||
return ((BasicQueryWalker) this.queryWalker).getPropertiesAsMap(propertyNames);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class allowing to specify custom {@link WalkerCallback} implementation or {@link BasicQueryWalker} extension.
|
||||
*/
|
||||
public static class WalkerSpecifier extends DefaultWalkerOperations<WalkerSpecifier>
|
||||
{
|
||||
public WalkerSpecifier(Query query)
|
||||
{
|
||||
super(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WalkerSpecifier self()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that OR operator instead of AND should be used while resolving the query.
|
||||
*/
|
||||
public DefaultWalkerOperations<? extends DefaultWalkerOperations<?>> usingOrOperator()
|
||||
{
|
||||
this.orQueryWalkerSupplier = (propertyNames) -> new BasicQueryWalker(propertyNames)
|
||||
{
|
||||
@Override
|
||||
public void or() {/*Enable OR support, disable AND support*/}
|
||||
@Override
|
||||
public void and() {throw UNSUPPORTED;}
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to specify custom {@link BasicQueryWalker} extension, which should be used to resolve the query.
|
||||
*/
|
||||
public <T extends BasicQueryWalker> DefaultWalkerOperations<? extends DefaultWalkerOperations<?>> usingWalker(final T queryWalker)
|
||||
{
|
||||
this.queryWalker = queryWalker;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to specify custom {@link WalkerCallback} implementation, which should be used to resolve the query.
|
||||
*/
|
||||
public <T extends WalkerCallback> QueryResolver<? extends QueryResolver<?>> usingWalker(final T queryWalker)
|
||||
{
|
||||
this.queryWalker = queryWalker;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,351 +0,0 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 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.framework.resource.parameters.where;
|
||||
|
||||
import static java.util.function.Predicate.not;
|
||||
|
||||
import static org.alfresco.rest.framework.resource.parameters.where.BasicQueryWalker.MISSING_ANY_CLAUSE_OF_TYPE;
|
||||
import static org.alfresco.rest.framework.resource.parameters.where.BasicQueryWalker.MISSING_CLAUSE_TYPE;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
|
||||
/**
|
||||
* Map composed of property comparison type and compared values.
|
||||
* Map key is clause (comparison) type.
|
||||
*/
|
||||
public class WhereProperty extends HashMap<WhereProperty.ClauseType, Collection<String>>
|
||||
{
|
||||
private final String name;
|
||||
private boolean validateStrictly;
|
||||
|
||||
public WhereProperty(final String name, final ClauseType clauseType, final Collection<String> values)
|
||||
{
|
||||
super(Map.of(clauseType, new HashSet<>(values)));
|
||||
this.name = name;
|
||||
this.validateStrictly = true;
|
||||
}
|
||||
|
||||
public WhereProperty(final String name, final ClauseType clauseType, final Collection<String> values, final boolean validateStrictly)
|
||||
{
|
||||
this(name, clauseType, values);
|
||||
this.validateStrictly = validateStrictly;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void addValuesToType(final ClauseType clauseType, final Collection<String> values)
|
||||
{
|
||||
if (this.containsKey(clauseType))
|
||||
{
|
||||
this.get(clauseType).addAll(values);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.put(clauseType, new HashSet<>(values));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsType(final ClauseType clauseType)
|
||||
{
|
||||
return this.containsKey(clauseType);
|
||||
}
|
||||
|
||||
public boolean containsType(final int clauseType, final boolean negated)
|
||||
{
|
||||
return this.containsKey(ClauseType.of(clauseType, negated));
|
||||
}
|
||||
|
||||
public boolean containsAllTypes(final ClauseType... clauseType)
|
||||
{
|
||||
return Arrays.stream(clauseType).distinct().filter(this::containsKey).count() == clauseType.length;
|
||||
}
|
||||
|
||||
public boolean containsAnyOfTypes(final ClauseType... clauseType)
|
||||
{
|
||||
return Arrays.stream(clauseType).distinct().anyMatch(this::containsKey);
|
||||
}
|
||||
|
||||
public Collection<String> getExpectedValuesFor(final ClauseType clauseType)
|
||||
{
|
||||
verifyAllClausesPresence(clauseType);
|
||||
return this.get(clauseType);
|
||||
}
|
||||
|
||||
public HashMap<ClauseType, Collection<String>> getExpectedValuesForAllOf(final ClauseType... clauseTypes)
|
||||
{
|
||||
verifyAllClausesPresence(clauseTypes);
|
||||
return Arrays.stream(clauseTypes)
|
||||
.distinct()
|
||||
.collect(Collectors.toMap(type -> type, this::get, (type1, type2) -> type1, MultiTypeNegatableValuesMap::new));
|
||||
}
|
||||
|
||||
public HashMap<ClauseType, Collection<String>> getExpectedValuesForAnyOf(final ClauseType... clauseTypes)
|
||||
{
|
||||
verifyAnyClausesPresence(clauseTypes);
|
||||
return Arrays.stream(clauseTypes)
|
||||
.distinct()
|
||||
.collect(Collectors.toMap(type -> type, this::get, (type1, type2) -> type1, MultiTypeNegatableValuesMap::new));
|
||||
}
|
||||
|
||||
public Collection<String> getExpectedValuesFor(final int clauseType, final boolean negated)
|
||||
{
|
||||
verifyAllClausesPresence(ClauseType.of(clauseType, negated));
|
||||
return this.get(ClauseType.of(clauseType, negated));
|
||||
}
|
||||
|
||||
public NegatableValuesMap getExpectedValuesFor(final int clauseType)
|
||||
{
|
||||
verifyAllClausesPresence(clauseType);
|
||||
final NegatableValuesMap values = new NegatableValuesMap();
|
||||
final ClauseType type = ClauseType.of(clauseType);
|
||||
final ClauseType negatedType = type.negate();
|
||||
if (this.containsKey(type))
|
||||
{
|
||||
values.put(false, this.get(type));
|
||||
}
|
||||
if (this.containsKey(negatedType))
|
||||
{
|
||||
values.put(true, this.get(negatedType));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
public MultiTypeNegatableValuesMap getExpectedValuesForAllOf(final int... clauseTypes)
|
||||
{
|
||||
verifyAllClausesPresence(clauseTypes);
|
||||
return getExpectedValuesFor(clauseTypes);
|
||||
}
|
||||
|
||||
public MultiTypeNegatableValuesMap getExpectedValuesForAnyOf(final int... clauseTypes)
|
||||
{
|
||||
verifyAnyClausesPresence(clauseTypes);
|
||||
return getExpectedValuesFor(clauseTypes);
|
||||
}
|
||||
|
||||
private MultiTypeNegatableValuesMap getExpectedValuesFor(final int... clauseTypes)
|
||||
{
|
||||
final MultiTypeNegatableValuesMap values = new MultiTypeNegatableValuesMap();
|
||||
Arrays.stream(clauseTypes).distinct().forEach(clauseType -> {
|
||||
final ClauseType type = ClauseType.of(clauseType);
|
||||
final ClauseType negatedType = type.negate();
|
||||
if (this.containsKey(type))
|
||||
{
|
||||
values.put(type, this.get(type));
|
||||
}
|
||||
if (this.containsKey(negatedType))
|
||||
{
|
||||
values.put(negatedType, this.get(negatedType));
|
||||
}
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if all specified clause types are present in this map, if not than throw {@link InvalidQueryException}.
|
||||
*/
|
||||
private void verifyAllClausesPresence(final ClauseType... clauseTypes)
|
||||
{
|
||||
if (validateStrictly)
|
||||
{
|
||||
Arrays.stream(clauseTypes).distinct().forEach(clauseType -> {
|
||||
if (!this.containsType(clauseType))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_CLAUSE_TYPE, this.name, WhereClauseParser.tokenNames[clauseType.getTypeNumber()]));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if all specified clause types are present in this map, if not than throw {@link InvalidQueryException}.
|
||||
* Exception is thrown when both, negated and non-negated types are missing.
|
||||
*/
|
||||
private void verifyAllClausesPresence(final int... clauseTypes)
|
||||
{
|
||||
if (validateStrictly)
|
||||
{
|
||||
Arrays.stream(clauseTypes).distinct().forEach(clauseType -> {
|
||||
if (!this.containsType(clauseType, false) && !this.containsType(clauseType, true))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_CLAUSE_TYPE, this.name, WhereClauseParser.tokenNames[clauseType]));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if any of specified clause types are present in this map, if not than throw {@link InvalidQueryException}.
|
||||
*/
|
||||
private void verifyAnyClausesPresence(final ClauseType... clauseTypes)
|
||||
{
|
||||
if (validateStrictly)
|
||||
{
|
||||
if (!this.containsAnyOfTypes(clauseTypes))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_ANY_CLAUSE_OF_TYPE,
|
||||
this.name, Arrays.stream(clauseTypes).map(type -> WhereClauseParser.tokenNames[type.getTypeNumber()]).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if any of specified clause types are present in this map, if not than throw {@link InvalidQueryException}.
|
||||
* Exception is thrown when both, negated and non-negated types are missing.
|
||||
*/
|
||||
private void verifyAnyClausesPresence(final int... clauseTypes)
|
||||
{
|
||||
if (validateStrictly)
|
||||
{
|
||||
final Collection<ClauseType> expectedTypes = Arrays.stream(clauseTypes)
|
||||
.distinct()
|
||||
.boxed()
|
||||
.flatMap(type -> Stream.of(ClauseType.of(type), ClauseType.of(type, true)))
|
||||
.collect(Collectors.toSet());
|
||||
if (!this.containsAnyOfTypes(expectedTypes.toArray(ClauseType[]::new)))
|
||||
{
|
||||
throw new InvalidQueryException(String.format(MISSING_ANY_CLAUSE_OF_TYPE,
|
||||
this.name, Arrays.stream(clauseTypes).mapToObj(type -> WhereClauseParser.tokenNames[type]).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ClauseType
|
||||
{
|
||||
EQUALS(WhereClauseParser.EQUALS),
|
||||
NOT_EQUALS(WhereClauseParser.EQUALS, true),
|
||||
GREATER_THAN(WhereClauseParser.GREATERTHAN),
|
||||
NOT_GREATER_THAN(WhereClauseParser.GREATERTHAN, true),
|
||||
LESS_THAN(WhereClauseParser.LESSTHAN),
|
||||
NOT_LESS_THAN(WhereClauseParser.LESSTHAN, true),
|
||||
GREATER_THAN_OR_EQUALS(WhereClauseParser.GREATERTHANOREQUALS),
|
||||
NOT_GREATER_THAN_OR_EQUALS(WhereClauseParser.GREATERTHANOREQUALS, true),
|
||||
LESS_THAN_OR_EQUALS(WhereClauseParser.LESSTHANOREQUALS),
|
||||
NOT_LESS_THAN_OR_EQUALS(WhereClauseParser.LESSTHANOREQUALS, true),
|
||||
BETWEEN(WhereClauseParser.BETWEEN),
|
||||
NOT_BETWEEN(WhereClauseParser.BETWEEN, true),
|
||||
IN(WhereClauseParser.IN),
|
||||
NOT_IN(WhereClauseParser.IN, true),
|
||||
MATCHES(WhereClauseParser.MATCHES),
|
||||
NOT_MATCHES(WhereClauseParser.MATCHES, true),
|
||||
EXISTS(WhereClauseParser.EXISTS),
|
||||
NOT_EXISTS(WhereClauseParser.EXISTS, true);
|
||||
|
||||
private final int typeNumber;
|
||||
private final boolean negated;
|
||||
|
||||
ClauseType(final int typeNumber)
|
||||
{
|
||||
this.typeNumber = typeNumber;
|
||||
this.negated = false;
|
||||
}
|
||||
|
||||
ClauseType(final int typeNumber, final boolean negated)
|
||||
{
|
||||
this.typeNumber = typeNumber;
|
||||
this.negated = negated;
|
||||
}
|
||||
|
||||
public static ClauseType of(final int type)
|
||||
{
|
||||
return of(type, false);
|
||||
}
|
||||
|
||||
public static ClauseType of(final int type, final boolean negated)
|
||||
{
|
||||
return Arrays.stream(ClauseType.values())
|
||||
.filter(clauseType -> clauseType.typeNumber == type && clauseType.negated == negated)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
public ClauseType negate()
|
||||
{
|
||||
return of(typeNumber, !negated);
|
||||
}
|
||||
|
||||
public int getTypeNumber()
|
||||
{
|
||||
return typeNumber;
|
||||
}
|
||||
|
||||
public boolean isNegated()
|
||||
{
|
||||
return negated;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NegatableValuesMap extends HashMap<Boolean, Collection<String>>
|
||||
{
|
||||
public Collection<String> skipNegated()
|
||||
{
|
||||
return this.get(false);
|
||||
}
|
||||
|
||||
public Collection<String> onlyNegated()
|
||||
{
|
||||
return this.get(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiTypeNegatableValuesMap extends HashMap<ClauseType, Collection<String>>
|
||||
{
|
||||
public Map<Integer, Collection<String>> skipNegated()
|
||||
{
|
||||
return this.keySet().stream()
|
||||
.filter(not(ClauseType::isNegated))
|
||||
.collect(Collectors.toMap(key -> key.typeNumber, this::get));
|
||||
}
|
||||
|
||||
public Collection<String> skipNegated(final int clauseType)
|
||||
{
|
||||
return this.get(ClauseType.of(clauseType));
|
||||
}
|
||||
|
||||
public Map<Integer, Collection<String>> onlyNegated()
|
||||
{
|
||||
return this.keySet().stream()
|
||||
.filter(not(ClauseType::isNegated))
|
||||
.collect(Collectors.toMap(key -> key.typeNumber, this::get));
|
||||
}
|
||||
|
||||
public Collection<String> onlyNegated(final int clauseType)
|
||||
{
|
||||
return this.get(ClauseType.of(clauseType, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,32 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.workflow.api.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -52,7 +51,7 @@ import org.apache.commons.beanutils.ConvertUtils;
|
||||
* {@link InvalidArgumentException} is thrown unless the method
|
||||
* {@link #handleUnmatchedComparison(int, String, String)} returns true (default
|
||||
* implementation returns false).
|
||||
*
|
||||
*
|
||||
* @author Frederik Heremans
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
@@ -73,21 +72,21 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
private Map<String, String> equalsProperties;
|
||||
|
||||
private Map<String, String> matchesProperties;
|
||||
|
||||
|
||||
private Map<String, String> greaterThanProperties;
|
||||
|
||||
|
||||
private Map<String, String> greaterThanOrEqualProperties;
|
||||
|
||||
|
||||
private Map<String, String> lessThanProperties;
|
||||
|
||||
|
||||
private Map<String, String> lessThanOrEqualProperties;
|
||||
|
||||
|
||||
private List<QueryVariableHolder> variableProperties;
|
||||
|
||||
|
||||
private boolean variablesEnabled;
|
||||
|
||||
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
public MapBasedQueryWalker(Set<String> supportedEqualsParameters, Set<String> supportedMatchesParameters)
|
||||
@@ -133,7 +132,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
lessThanOrEqualProperties = new HashMap<String, String>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void enableVariablesSupport(NamespaceService namespaceService, DictionaryService dictionaryService)
|
||||
{
|
||||
variablesEnabled = true;
|
||||
@@ -149,7 +148,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
this.dictionaryService = dictionaryService;
|
||||
variableProperties = new ArrayList<QueryVariableHolder>();
|
||||
}
|
||||
|
||||
|
||||
public List<QueryVariableHolder> getVariableProperties() {
|
||||
return variableProperties;
|
||||
}
|
||||
@@ -159,9 +158,9 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
{
|
||||
if(negated)
|
||||
{
|
||||
throw new InvalidArgumentException("Cannot use negated matching for property: " + property);
|
||||
throw new InvalidArgumentException("Cannot use negated matching for property: " + property);
|
||||
}
|
||||
if (variablesEnabled && property.startsWith("variables/"))
|
||||
if (variablesEnabled && property.startsWith("variables/"))
|
||||
{
|
||||
processVariable(property, value, WhereClauseParser.MATCHES);
|
||||
}
|
||||
@@ -171,19 +170,19 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidArgumentException("Cannot use matching for property: " + property);
|
||||
throw new InvalidArgumentException("Cannot use matching for property: " + property);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void comparison(int type, String propertyName, String propertyValue, boolean negated)
|
||||
{
|
||||
if (variablesEnabled && propertyName.startsWith("variables/"))
|
||||
if (variablesEnabled && propertyName.startsWith("variables/"))
|
||||
{
|
||||
processVariable(propertyName, propertyValue, type);
|
||||
processVariable(propertyName, propertyValue, type);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean throwError = false;
|
||||
if (type == WhereClauseParser.EQUALS)
|
||||
{
|
||||
@@ -193,7 +192,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else if (type == WhereClauseParser.MATCHES)
|
||||
@@ -204,7 +203,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else if (type == WhereClauseParser.GREATERTHAN)
|
||||
@@ -215,7 +214,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else if (type == WhereClauseParser.GREATERTHANOREQUALS)
|
||||
@@ -226,7 +225,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else if (type == WhereClauseParser.LESSTHAN)
|
||||
@@ -237,7 +236,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else if (type == WhereClauseParser.LESSTHANOREQUALS)
|
||||
@@ -248,7 +247,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
else
|
||||
{
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -256,24 +255,15 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
throwError = !handleUnmatchedComparison(type, propertyName, propertyValue);
|
||||
}
|
||||
|
||||
if (throwError)
|
||||
{
|
||||
throw new InvalidArgumentException("framework.exception.InvalidProperty", new Object[] {propertyName, propertyValue, WhereClauseParser.tokenNames[type]});
|
||||
if (throwError)
|
||||
{
|
||||
throw new InvalidArgumentException("framework.exception.InvalidProperty", new Object[] {propertyName, propertyValue, WhereClauseParser.tokenNames[type]});
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
// Throw error for the unsupported negation only if the property was valid for comparison, show the more meaningful error first.
|
||||
throw new InvalidArgumentException("Cannot use NOT for " + WhereClauseParser.tokenNames[type] + " comparison.");
|
||||
}
|
||||
else if (negated)
|
||||
{
|
||||
// Throw error for the unsupported negation only if the property was valid for comparison, show the more meaningful error first.
|
||||
throw new InvalidArgumentException("Cannot use NOT for " + WhereClauseParser.tokenNames[type] + " comparison.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expected value for property and comparison type. This class supports only non-negated comparisons, thus parameter negated is ignored in bellow method.
|
||||
*/
|
||||
@Override
|
||||
public Collection<String> getProperty(String propertyName, int type, boolean negated)
|
||||
{
|
||||
return Set.of(this.getProperty(propertyName, type));
|
||||
}
|
||||
|
||||
public String getProperty(String propertyName, int type)
|
||||
@@ -310,7 +300,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
|
||||
/**
|
||||
* Get the property value, converted to the requested type.
|
||||
*
|
||||
*
|
||||
* @param propertyName name of the parameter
|
||||
* @param type int
|
||||
* @param returnType type of object to return
|
||||
@@ -344,7 +334,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
{
|
||||
// Conversion failed, wrap in Illegal
|
||||
throw new InvalidArgumentException("Query property value for '" + propertyName + "' should be a valid "
|
||||
+ returnType.getSimpleName());
|
||||
+ returnType.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +345,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
// method indicates that AND is
|
||||
// supported. OR is not supported at the same time.
|
||||
}
|
||||
|
||||
|
||||
protected void processVariable(String propertyName, String propertyValue, int type)
|
||||
{
|
||||
String localPropertyName = propertyName.replaceFirst("variables/", "");
|
||||
@@ -363,25 +353,25 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
DataTypeDefinition dataTypeDefinition = null;
|
||||
// variable scope global is default
|
||||
String scopeDef = "global";
|
||||
|
||||
|
||||
// look for variable scope
|
||||
if (localPropertyName.contains("local/"))
|
||||
{
|
||||
scopeDef = "local";
|
||||
localPropertyName = localPropertyName.replaceFirst("local/", "");
|
||||
}
|
||||
|
||||
|
||||
if (localPropertyName.contains("global/"))
|
||||
{
|
||||
localPropertyName = localPropertyName.replaceFirst("global/", "");
|
||||
}
|
||||
|
||||
|
||||
// look for variable type definition
|
||||
if ((propertyValue.contains("_") || propertyValue.contains(":")) && propertyValue.contains(" "))
|
||||
if ((propertyValue.contains("_") || propertyValue.contains(":")) && propertyValue.contains(" "))
|
||||
{
|
||||
int indexOfSpace = propertyValue.indexOf(' ');
|
||||
if ((propertyValue.contains("_") && indexOfSpace > propertyValue.indexOf("_")) ||
|
||||
(propertyValue.contains(":") && indexOfSpace > propertyValue.indexOf(":")))
|
||||
if ((propertyValue.contains("_") && indexOfSpace > propertyValue.indexOf("_")) ||
|
||||
(propertyValue.contains(":") && indexOfSpace > propertyValue.indexOf(":")))
|
||||
{
|
||||
String typeDef = propertyValue.substring(0, indexOfSpace);
|
||||
try
|
||||
@@ -396,7 +386,7 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dataTypeDefinition != null && "java.util.Date".equalsIgnoreCase(dataTypeDefinition.getJavaClassName()))
|
||||
{
|
||||
// fix for different ISO 8601 Date format classes in Alfresco (org.alfresco.util and Spring Surf)
|
||||
@@ -406,18 +396,18 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
{
|
||||
actualValue = DefaultTypeConverter.INSTANCE.convert(dataTypeDefinition, propertyValue);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
actualValue = propertyValue;
|
||||
}
|
||||
|
||||
|
||||
variableProperties.add(new QueryVariableHolder(localPropertyName, type, actualValue, scopeDef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when unsupported property is encountered or comparison operator
|
||||
* other than equals.
|
||||
*
|
||||
*
|
||||
* @return true, if the comparison is handles successfully. False, if an
|
||||
* exception should be thrown because the comparison can't be
|
||||
* handled.
|
||||
@@ -426,25 +416,25 @@ public class MapBasedQueryWalker extends WalkerCallbackAdapter
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static class QueryVariableHolder implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private String propertyName;
|
||||
private int operator;
|
||||
private Object propertyValue;
|
||||
private String scope;
|
||||
|
||||
|
||||
public QueryVariableHolder() {}
|
||||
|
||||
|
||||
public QueryVariableHolder(String propertyName, int operator, Object propertyValue, String scope) {
|
||||
this.propertyName = propertyName;
|
||||
this.operator = operator;
|
||||
this.propertyValue = propertyValue;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
|
||||
public String getPropertyName()
|
||||
{
|
||||
return propertyName;
|
||||
|
||||
@@ -858,7 +858,6 @@
|
||||
<property name="taggingService" ref="TaggingService" />
|
||||
<property name="authorityService" ref="AuthorityService" />
|
||||
<property name="typeConstraint" ref="nodeTypeConstraint" />
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="Tags" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
|
||||
@@ -30,9 +30,11 @@ import org.alfresco.rest.api.categories.CategoriesEntityResourceTest;
|
||||
import org.alfresco.rest.api.categories.NodesCategoryLinksRelationTest;
|
||||
import org.alfresco.rest.api.categories.SubcategoriesRelationTest;
|
||||
import org.alfresco.rest.api.impl.CategoriesImplTest;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@Experimental
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
CategoriesImplTest.class,
|
||||
|
||||
@@ -27,9 +27,11 @@ package org.alfresco.rest.api;
|
||||
|
||||
import org.alfresco.rest.api.impl.TagsImplTest;
|
||||
import org.alfresco.rest.api.tags.TagsEntityResourceTest;
|
||||
import org.alfresco.service.Experimental;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@Experimental
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
TagsImplTest.class,
|
||||
|
||||
@@ -60,7 +60,6 @@ import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.transfer.PathHelper;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Category;
|
||||
import org.alfresco.rest.api.model.Node;
|
||||
@@ -72,7 +71,6 @@ import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
@@ -102,9 +100,6 @@ public class CategoriesImplTest
|
||||
private static final Category CATEGORY = createDefaultCategory();
|
||||
private static final String CONTENT_NODE_ID = "content-node-id";
|
||||
private static final NodeRef CONTENT_NODE_REF = createNodeRefWithId(CONTENT_NODE_ID);
|
||||
private static final String MOCK_ROOT_LEVEL = "/{mockRootLevel}";
|
||||
private static final String MOCK_CHILD_LEVEL = "/{mockChild}";
|
||||
private static final String MOCK_CATEGORY_PATH = "//" + MOCK_ROOT_LEVEL + "//" + MOCK_CHILD_LEVEL;
|
||||
|
||||
@Mock
|
||||
private Nodes nodesMock;
|
||||
@@ -133,7 +128,7 @@ public class CategoriesImplTest
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
given(nodesMock.validateNode(CATEGORY_ID)).willReturn(CATEGORY_NODE_REF);
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willReturn(CONTENT_NODE_REF);
|
||||
given(nodesMock.validateNode(CONTENT_NODE_ID)).willReturn(CONTENT_NODE_REF);
|
||||
given(nodesMock.isSubClass(any(), any(), anyBoolean())).willReturn(true);
|
||||
given(typeConstraint.matches(any())).willReturn(true);
|
||||
given(permissionServiceMock.hasReadPermission(any())).willReturn(AccessStatus.ALLOWED);
|
||||
@@ -257,27 +252,6 @@ public class CategoriesImplTest
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryById_includePath()
|
||||
{
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.getCategoryById(CATEGORY_ID, parametersMock);
|
||||
|
||||
assertThat(actualCategory)
|
||||
.isNotNull()
|
||||
.extracting(Category::getPath)
|
||||
.isNotNull()
|
||||
.isEqualTo(MOCK_CATEGORY_PATH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryById_notACategory()
|
||||
{
|
||||
@@ -505,36 +479,6 @@ public class CategoriesImplTest
|
||||
.isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCategory_includePath()
|
||||
{
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef categoryNodeRef = createNodeRefWithId(CATEGORY_ID);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(categoryServiceMock.createCategory(parentCategoryNodeRef, CATEGORY_NAME)).willReturn(categoryNodeRef);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
final List<Category> categoryModels = new ArrayList<>(prepareCategories());
|
||||
|
||||
// when
|
||||
final List<Category> actualCreatedCategories = objectUnderTest.createSubcategories(PARENT_ID, categoryModels, parametersMock);
|
||||
|
||||
then(categoryServiceMock).should().createCategory(any(), any());
|
||||
then(categoryServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
assertThat(actualCreatedCategories)
|
||||
.isNotNull()
|
||||
.hasSize(1)
|
||||
.element(0)
|
||||
.extracting(Category::getPath)
|
||||
.isNotNull()
|
||||
.isEqualTo(MOCK_CATEGORY_PATH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCategories_noPermissions()
|
||||
{
|
||||
@@ -684,30 +628,6 @@ public class CategoriesImplTest
|
||||
.isEqualTo(List.of(0, 2, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren_includePath()
|
||||
{
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
given(nodesMock.validateNode(PARENT_ID)).willReturn(parentCategoryNodeRef);
|
||||
given(nodesMock.isSubClass(parentCategoryNodeRef, ContentModel.TYPE_CATEGORY, false)).willReturn(true);
|
||||
final int childrenCount = 3;
|
||||
final List<ChildAssociationRef> childAssociationRefMocks = prepareChildAssocMocks(childrenCount, parentCategoryNodeRef);
|
||||
given(nodeServiceMock.getChildAssocs(parentCategoryNodeRef)).willReturn(childAssociationRefMocks);
|
||||
childAssociationRefMocks.forEach(this::prepareCategoryNodeMocks);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
|
||||
// when
|
||||
final List<Category> actualCategoryChildren = objectUnderTest.getCategoryChildren(PARENT_ID, parametersMock);
|
||||
|
||||
assertThat(actualCategoryChildren)
|
||||
.isNotNull()
|
||||
.hasSize(3)
|
||||
.extracting(Category::getPath)
|
||||
.isNotNull()
|
||||
.isEqualTo(List.of(MOCK_CATEGORY_PATH, MOCK_CATEGORY_PATH, MOCK_CATEGORY_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCategoryChildren_noChildren()
|
||||
{
|
||||
@@ -831,32 +751,6 @@ public class CategoriesImplTest
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCategoryById_includePath()
|
||||
{
|
||||
final String categoryNewName = "categoryNewName";
|
||||
final Category fixedCategory = createCategoryOnlyWithName(categoryNewName);
|
||||
// simulate path provided by client to check if it will be ignored
|
||||
fixedCategory.setPath("/test/TestCat");
|
||||
final QName categoryQName = createCmQNameOf(CATEGORY_NAME);
|
||||
final NodeRef parentCategoryNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, categoryQName);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode(categoryNewName));
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.moveNode(any(), any(), any(), any())).willReturn(createAssociationOf(parentCategoryNodeRef, CATEGORY_NODE_REF, createCmQNameOf(categoryNewName)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
|
||||
// when
|
||||
final Category actualCategory = objectUnderTest.updateCategoryById(CATEGORY_ID, fixedCategory, parametersMock);
|
||||
|
||||
assertThat(actualCategory)
|
||||
.isNotNull()
|
||||
.extracting(Category::getPath)
|
||||
.isNotNull()
|
||||
.isEqualTo(MOCK_CATEGORY_PATH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateCategoryById_noPermission()
|
||||
{
|
||||
@@ -1006,7 +900,7 @@ public class CategoriesImplTest
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, categoryLinks, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasPermission(CONTENT_NODE_REF, PermissionService.CHANGE_PERMISSIONS);
|
||||
then(permissionServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
@@ -1024,7 +918,6 @@ public class CategoriesImplTest
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryParentNodeRef);
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Category> expectedLinkedCategories = List.of(CATEGORY);
|
||||
expectedLinkedCategories.get(0).setPath(null);
|
||||
assertThat(actualLinkedCategories)
|
||||
.isNotNull().usingRecursiveComparison()
|
||||
.isEqualTo(expectedLinkedCategories);
|
||||
@@ -1091,36 +984,6 @@ public class CategoriesImplTest
|
||||
.isEqualTo(expectedLinkedCategories);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkNodeToCategories_includePath()
|
||||
{
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(nodeServiceMock.hasAspect(any(), any())).willReturn(true);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
|
||||
// when
|
||||
final List<Category> actualLinkedCategories = objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock);
|
||||
|
||||
then(nodesMock).should(times(2)).getNode(CATEGORY_ID);
|
||||
then(nodeServiceMock).should().getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).should().getPrimaryParent(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getParentAssocs(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().hasAspect(CONTENT_NODE_REF, ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||
then(nodeServiceMock).should().getProperty(CONTENT_NODE_REF, ContentModel.PROP_CATEGORIES);
|
||||
final Serializable expectedCategories = (Serializable) List.of(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().setProperty(CONTENT_NODE_REF, ContentModel.PROP_CATEGORIES, expectedCategories);
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryParentNodeRef);
|
||||
final List<Category> expectedLinkedCategories = List.of(CATEGORY);
|
||||
expectedLinkedCategories.get(0).setPath(MOCK_CATEGORY_PATH);
|
||||
assertThat(actualLinkedCategories)
|
||||
.isNotNull().usingRecursiveComparison()
|
||||
.isEqualTo(expectedLinkedCategories);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkNodeToCategories_withPreviouslyLinkedCategories()
|
||||
{
|
||||
@@ -1148,12 +1011,12 @@ public class CategoriesImplTest
|
||||
@Test
|
||||
public void testLinkNodeToCategories_withInvalidNodeId()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
given(nodesMock.validateNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).shouldHaveNoInteractions();
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
@@ -1168,7 +1031,7 @@ public class CategoriesImplTest
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.linkNodeToCategories(CONTENT_NODE_ID, List.of(CATEGORY), parametersMock));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasPermission(CONTENT_NODE_REF, PermissionService.CHANGE_PERMISSIONS);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
@@ -1255,7 +1118,7 @@ public class CategoriesImplTest
|
||||
objectUnderTest.unlinkNodeFromCategory(CONTENT_NODE_ID, CATEGORY_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateNode(CATEGORY_ID);
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasPermission(CONTENT_NODE_REF, PermissionService.CHANGE_PERMISSIONS);
|
||||
then(permissionServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
@@ -1292,7 +1155,7 @@ public class CategoriesImplTest
|
||||
// when
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasReadPermission(CONTENT_NODE_REF);
|
||||
then(permissionServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
@@ -1305,55 +1168,20 @@ public class CategoriesImplTest
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryParentNodeRef);
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Category> expectedCategories = List.of(CATEGORY);
|
||||
expectedCategories.get(0).setPath(null);
|
||||
assertThat(actualCategories)
|
||||
.isNotNull().usingRecursiveComparison()
|
||||
.isEqualTo(expectedCategories);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListCategoriesForNode_includePath()
|
||||
{
|
||||
final NodeRef categoryParentNodeRef = createNodeRefWithId(PARENT_ID);
|
||||
final ChildAssociationRef parentAssociation = createAssociationOf(categoryParentNodeRef, CATEGORY_NODE_REF);
|
||||
given(nodeServiceMock.getProperty(any(), eq(ContentModel.PROP_CATEGORIES))).willReturn((Serializable) List.of(CATEGORY_NODE_REF));
|
||||
given(nodesMock.getNode(any())).willReturn(createNode());
|
||||
given(nodeServiceMock.getPrimaryParent(any())).willReturn(parentAssociation);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(Nodes.PARAM_INCLUDE_PATH));
|
||||
given(nodeServiceMock.getPath(any())).willReturn(mockCategoryPath());
|
||||
|
||||
// when
|
||||
final List<Category> actualCategories = objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasReadPermission(CONTENT_NODE_REF);
|
||||
then(permissionServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(typeConstraint).should().matches(CONTENT_NODE_REF);
|
||||
then(typeConstraint).shouldHaveNoMoreInteractions();
|
||||
then(nodesMock).should(times(2)).getNode(CATEGORY_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(nodeServiceMock).should().getProperty(CONTENT_NODE_REF, ContentModel.PROP_CATEGORIES);
|
||||
then(nodeServiceMock).should().getChildAssocs(CATEGORY_NODE_REF, RegexQNamePattern.MATCH_ALL, RegexQNamePattern.MATCH_ALL, false);
|
||||
then(nodeServiceMock).should().getPrimaryParent(CATEGORY_NODE_REF);
|
||||
then(nodeServiceMock).should().getParentAssocs(categoryParentNodeRef);
|
||||
then(nodeServiceMock).should().getPath(any());
|
||||
then(nodeServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Category> expectedCategories = List.of(CATEGORY);
|
||||
expectedCategories.get(0).setPath(MOCK_CATEGORY_PATH);
|
||||
assertThat(actualCategories)
|
||||
.isNotNull().usingRecursiveComparison()
|
||||
.isEqualTo(expectedCategories);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListCategoriesForNode_withInvalidNodeId()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
given(nodesMock.validateNode(CONTENT_NODE_ID)).willThrow(EntityNotFoundException.class);
|
||||
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
@@ -1367,7 +1195,7 @@ public class CategoriesImplTest
|
||||
// when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.listCategoriesForNode(CONTENT_NODE_ID, parametersMock));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(CONTENT_NODE_ID);
|
||||
then(nodesMock).should().validateNode(CONTENT_NODE_ID);
|
||||
then(permissionServiceMock).should().hasReadPermission(CONTENT_NODE_REF);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException)
|
||||
@@ -1501,13 +1329,4 @@ public class CategoriesImplTest
|
||||
{
|
||||
return new ChildAssociationRef(ContentModel.ASSOC_SUBCATEGORIES, parentNode, childNodeName, childNode);
|
||||
}
|
||||
|
||||
private Path mockCategoryPath()
|
||||
{
|
||||
final Path mockPath = new Path();
|
||||
mockPath.append(PathHelper.stringToPath(MOCK_ROOT_LEVEL));
|
||||
mockPath.append(PathHelper.stringToPath(MOCK_CHILD_LEVEL));
|
||||
mockPath.append(PathHelper.stringToPath("/"));
|
||||
return mockPath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,52 +25,32 @@
|
||||
*/
|
||||
package org.alfresco.rest.api.impl;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NOT_A_VALID_TAG;
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NO_PERMISSION_TO_MANAGE_A_TAG;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.Tag;
|
||||
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.UnsupportedResourceOperationException;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.SortColumn;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
|
||||
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.tagging.TaggingService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TypeConstraint;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -82,35 +62,17 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
public class TagsImplTest
|
||||
{
|
||||
private static final String TAG_ID = "tag-node-id";
|
||||
private static final String PARENT_NODE_ID = "tag:tag-root";
|
||||
private static final String TAG_NAME = "tag-dummy-name";
|
||||
private static final NodeRef TAG_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(TAG_NAME));
|
||||
private static final NodeRef TAG_PARENT_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, PARENT_NODE_ID);
|
||||
private static final String CONTENT_NODE_ID = "content-node-id";
|
||||
private static final NodeRef CONTENT_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, CONTENT_NODE_ID);
|
||||
private static final String PARAM_INCLUDE_COUNT = "count";
|
||||
|
||||
|
||||
private final RecognizedParamsExtractor queryExtractor = new RecognizedParamsExtractor() {};
|
||||
private static final NodeRef TAG_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
@Mock
|
||||
private Nodes nodesMock;
|
||||
@Mock
|
||||
private ChildAssociationRef primaryParentMock;
|
||||
@Mock
|
||||
private NodeService nodeServiceMock;
|
||||
@Mock
|
||||
private AuthorityService authorityServiceMock;
|
||||
@Mock
|
||||
private TaggingService taggingServiceMock;
|
||||
@Mock
|
||||
private Parameters parametersMock;
|
||||
@Mock
|
||||
private Paging pagingMock;
|
||||
@Mock
|
||||
private PagingResults<Pair<NodeRef, String>> pagingResultsMock;
|
||||
@Mock
|
||||
private TypeConstraint typeConstraintMock;
|
||||
|
||||
@InjectMocks
|
||||
private TagsImpl objectUnderTest;
|
||||
@@ -119,299 +81,36 @@ public class TagsImplTest
|
||||
public void setup()
|
||||
{
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(true);
|
||||
given(nodesMock.validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willReturn(TAG_NODE_REF);
|
||||
given(nodesMock.validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willReturn(TAG_NODE_REF);
|
||||
given(taggingServiceMock.getTagName(TAG_NODE_REF)).willReturn(TAG_NAME);
|
||||
given(nodeServiceMock.getPrimaryParent(TAG_NODE_REF)).willReturn(primaryParentMock);
|
||||
given(primaryParentMock.getParentRef()).willReturn(TAG_PARENT_NODE_REF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//given(taggingServiceMock.getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull())).willReturn(List.of(new Pair<>(TAG_NODE_REF, null)));
|
||||
given(taggingServiceMock.getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull())).willReturn(Map.of(TAG_NODE_REF, 0L));
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("tag-dummy-name");
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(List.of(TAG_NAME));
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_verifyIfCountIsZero()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT));
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), any(), any(), any())).willReturn(Map.of(TAG_NODE_REF, 0L));
|
||||
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("tag-dummy-name");
|
||||
public void testGetTags() {
|
||||
final List<String> tagNames = List.of("testTag","tag11");
|
||||
final List<Tag> tagsToCreate = createTags(tagNames);
|
||||
given(taggingServiceMock.createTags(any(), any())).willAnswer(invocation -> createTagAndNodeRefPairs(invocation.getArgument(1)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(List.of(TAG_NAME)).stream()
|
||||
.peek(tag -> tag.setCount(0L))
|
||||
.collect(toList());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
/** Check that we can get counts for two tags - one in use and one not applied to any nodes. */
|
||||
@Test
|
||||
public void testGetTags_verifyCountPopulatedCorrectly()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
|
||||
given(parametersMock.getSorting()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeA, 5L);
|
||||
results.put(tagNodeB, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), isNull(), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("taga", "tagb");
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("tagA").nodeRef(tagNodeA).count(5L).create(),
|
||||
Tag.builder().tag("tagB").nodeRef(tagNodeB).count(0L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByCountAscendingOrder()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
NodeRef tagNodeC = new NodeRef("tag://C/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("count", true)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeB, 0L);
|
||||
results.put(tagNodeC, 2L);
|
||||
results.put(tagNodeA, 5L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), eq(new Pair<>("count", true)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagNodeA, ContentModel.PROP_NAME)).willReturn("taga");
|
||||
given(nodeServiceMock.getProperty(tagNodeB, ContentModel.PROP_NAME)).willReturn("tagb");
|
||||
given(nodeServiceMock.getProperty(tagNodeC, ContentModel.PROP_NAME)).willReturn("tagc");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("tagb").nodeRef(tagNodeB).count(0L).create(),
|
||||
Tag.builder().tag("tagc").nodeRef(tagNodeC).count(2L).create(),
|
||||
Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByCountDescendingOrder()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
NodeRef tagNodeC = new NodeRef("tag://C/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("count", false)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeA, 5L);
|
||||
results.put(tagNodeC, 2L);
|
||||
results.put(tagNodeB, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), eq(new Pair<>("count", false)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagNodeA, ContentModel.PROP_NAME)).willReturn("taga");
|
||||
given(nodeServiceMock.getProperty(tagNodeB, ContentModel.PROP_NAME)).willReturn("tagb");
|
||||
given(nodeServiceMock.getProperty(tagNodeC, ContentModel.PROP_NAME)).willReturn("tagc");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create(),
|
||||
Tag.builder().tag("tagc").nodeRef(tagNodeC).count(2L).create(),
|
||||
Tag.builder().tag("tagb").nodeRef(tagNodeB).count(0L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByTagAscendingOrder()
|
||||
{
|
||||
NodeRef tagApple = new NodeRef("tag://apple/");
|
||||
NodeRef tagBanana = new NodeRef("tag://banana/");
|
||||
NodeRef tagCoconut = new NodeRef("tag://coconut/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("tag", true)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagApple, 0L);
|
||||
results.put(tagBanana, 0L);
|
||||
results.put(tagCoconut, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), eq(new Pair<>("tag", true)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagApple, ContentModel.PROP_NAME)).willReturn("apple");
|
||||
given(nodeServiceMock.getProperty(tagBanana, ContentModel.PROP_NAME)).willReturn("banana");
|
||||
given(nodeServiceMock.getProperty(tagCoconut, ContentModel.PROP_NAME)).willReturn("coconut");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("apple").nodeRef(tagApple).create(),
|
||||
Tag.builder().tag("banana").nodeRef(tagBanana).create(),
|
||||
Tag.builder().tag("coconut").nodeRef(tagCoconut).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByTagDescendingOrder()
|
||||
{
|
||||
NodeRef tagApple = new NodeRef("tag://apple/");
|
||||
NodeRef tagBanana = new NodeRef("tag://banana/");
|
||||
NodeRef tagCoconut = new NodeRef("tag://coconut/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("tag", false)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagCoconut, 0L);
|
||||
results.put(tagBanana, 0L);
|
||||
results.put(tagApple, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), eq(new Pair<>("tag", false)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagApple, ContentModel.PROP_NAME)).willReturn("apple");
|
||||
given(nodeServiceMock.getProperty(tagBanana, ContentModel.PROP_NAME)).willReturn("banana");
|
||||
given(nodeServiceMock.getProperty(tagCoconut, ContentModel.PROP_NAME)).willReturn("coconut");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("coconut").nodeRef(tagCoconut).create(),
|
||||
Tag.builder().tag("banana").nodeRef(tagBanana).create(),
|
||||
Tag.builder().tag("apple").nodeRef(tagApple).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withEqualsClauseWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag=expectedName)"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), eq(new ArrayList<>()), any(), eq(Set.of("expectedname")), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withInClauseWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag IN (expectedName1, expectedName2))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE),any(), any(), eq(Set.of("expectedname1", "expectedname2")), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withMatchesClauseWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag MATCHES ('expectedName*'))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), eq(Set.of("expectedname*")));
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withBothInAndEqualsClausesInSingleWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag=expectedName AND tag IN (expectedName1, expectedName2))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withOtherClauseInWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag BETWEEN ('expectedName', 'expectedName2'))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withNotEqualsClauseInWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(NOT tag=expectedName)"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream()
|
||||
.peek(tag -> tag.setCount(0))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(expectedTags, actualCreatedTags);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteTagById()
|
||||
{
|
||||
//when
|
||||
objectUnderTest.deleteTagById(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodesMock).should().validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
then(nodesMock).should().validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(taggingServiceMock).should().getTagName(TAG_NODE_REF);
|
||||
then(taggingServiceMock).should().deleteTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME);
|
||||
then(taggingServiceMock).should().deleteTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME);
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
|
||||
@@ -421,7 +120,7 @@ public class TagsImplTest
|
||||
given(authorityServiceMock.hasAdminAuthority()).willReturn(false);
|
||||
|
||||
//when
|
||||
assertThrows(PermissionDeniedException.class, () -> objectUnderTest.deleteTagById(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID));
|
||||
assertThrows(PermissionDeniedException.class, () -> objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID));
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
@@ -435,12 +134,12 @@ public class TagsImplTest
|
||||
public void testDeleteTagById_nonExistentTag()
|
||||
{
|
||||
//when
|
||||
assertThrows(EntityNotFoundException.class, () -> objectUnderTest.deleteTagById(STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id"));
|
||||
assertThrows(EntityNotFoundException.class, () -> objectUnderTest.deleteTagById(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id"));
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(nodesMock).should().validateNode(STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id");
|
||||
then(nodesMock).should().validateNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-id");
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
@@ -458,11 +157,11 @@ public class TagsImplTest
|
||||
|
||||
then(authorityServiceMock).should().hasAdminAuthority();
|
||||
then(authorityServiceMock).shouldHaveNoMoreInteractions();
|
||||
then(taggingServiceMock).should().createTags(STORE_REF_WORKSPACE_SPACESSTORE, tagNames);
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagNames);
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames);
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull().usingRecursiveComparison()
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
@@ -526,7 +225,7 @@ public class TagsImplTest
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.createTags(List.of(createTag(TAG_NAME)), parametersMock));
|
||||
|
||||
then(taggingServiceMock).should().createTags(STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualException).isInstanceOf(DuplicateChildNodeNameException.class);
|
||||
}
|
||||
@@ -541,7 +240,7 @@ public class TagsImplTest
|
||||
//when
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().createTags(STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
then(taggingServiceMock).should().createTags(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, List.of(TAG_NAME));
|
||||
final List<Tag> expectedTags = List.of(createTagWithNodeRef(TAG_NAME));
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
@@ -560,141 +259,18 @@ public class TagsImplTest
|
||||
final List<Tag> actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(tagNames).stream()
|
||||
.peek(tag -> tag.setCount(0L))
|
||||
.collect(toList());
|
||||
.peek(tag -> tag.setCount(0))
|
||||
.collect(Collectors.toList());
|
||||
assertThat(actualCreatedTags)
|
||||
.isNotNull()
|
||||
.isEqualTo(expectedTags);
|
||||
}
|
||||
|
||||
@Test(expected = EntityNotFoundException.class)
|
||||
public void testGetTagByIdNotFoundValidation()
|
||||
{
|
||||
given(nodesMock.validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willThrow(EntityNotFoundException.class);
|
||||
objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, null);
|
||||
then(nodeServiceMock).shouldHaveNoInteractions();
|
||||
then(nodesMock).should().validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(taggingServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddTags()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willReturn(CONTENT_NODE_REF);
|
||||
given(typeConstraintMock.matches(CONTENT_NODE_REF)).willReturn(true);
|
||||
List<Pair<String, NodeRef>> pairs = List.of(new Pair<>("taga", new NodeRef("tag://A/")), new Pair<>("tagb", new NodeRef("tag://B/")));
|
||||
List<String> tagNames = pairs.stream().map(Pair::getFirst).collect(toList());
|
||||
List<Tag> tags = tagNames.stream().map(name -> Tag.builder().tag(name).create()).collect(toList());
|
||||
given(taggingServiceMock.addTags(CONTENT_NODE_REF, tagNames)).willReturn(pairs);
|
||||
given(taggingServiceMock.findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE)).willReturn(List.of(new Pair<>("taga", 4)));
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
|
||||
List<Tag> actual = objectUnderTest.addTags(CONTENT_NODE_ID, tags, parametersMock);
|
||||
|
||||
final List<Tag> expected = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create(),
|
||||
Tag.builder().tag("tagb").nodeRef(tagNodeB).count(1L).create());
|
||||
assertEquals("Unexpected tags returned.", expected, actual);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidArgumentException.class)
|
||||
public void testAddTagsToInvalidNode()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willThrow(new InvalidArgumentException());
|
||||
List<Tag> tags = List.of(Tag.builder().tag("tag1").create());
|
||||
|
||||
objectUnderTest.addTags(CONTENT_NODE_ID, tags, parametersMock);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedResourceOperationException.class)
|
||||
public void testAddTagsToWrongTypeOfNode()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willReturn(CONTENT_NODE_REF);
|
||||
given(typeConstraintMock.matches(CONTENT_NODE_REF)).willReturn(false);
|
||||
|
||||
List<Tag> tags = List.of(Tag.builder().tag("tag1").create());
|
||||
|
||||
objectUnderTest.addTags(CONTENT_NODE_ID, tags, parametersMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTagsForNode()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willReturn(CONTENT_NODE_REF);
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
List<Pair<NodeRef, String>> pairs = List.of(new Pair<>(new NodeRef("tag://A/"), "taga"), new Pair<>(new NodeRef("tag://B/"), "tagb"));
|
||||
given(taggingServiceMock.getTags(eq(CONTENT_NODE_REF), any(PagingRequest.class))).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(null, null));
|
||||
given(pagingResultsMock.getPage()).willReturn(pairs);
|
||||
|
||||
CollectionWithPagingInfo<Tag> actual = objectUnderTest.getTags(CONTENT_NODE_ID, parametersMock);
|
||||
|
||||
List<Tag> tags = pairs.stream().map(pair -> Tag.builder().tag(pair.getSecond()).nodeRef(pair.getFirst()).create()).collect(toList());
|
||||
assertEquals(actual.getCollection(), tags);
|
||||
}
|
||||
|
||||
@Test (expected = InvalidArgumentException.class)
|
||||
public void testGetTagsFromInvalidNode()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(CONTENT_NODE_ID)).willThrow(new InvalidArgumentException());
|
||||
|
||||
objectUnderTest.getTags(CONTENT_NODE_ID, parametersMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeTag()
|
||||
{
|
||||
Tag suppliedTag = Tag.builder().tag("new-name").create();
|
||||
given(taggingServiceMock.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME, "new-name")).willReturn(TAG_NODE_REF);
|
||||
|
||||
Tag tag = objectUnderTest.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, suppliedTag, parametersMock);
|
||||
|
||||
Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag("new-name").create();
|
||||
assertEquals("Unexpected return value", expected, tag);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeTagAndGetCount()
|
||||
{
|
||||
Tag suppliedTag = Tag.builder().tag("new-name").create();
|
||||
given(taggingServiceMock.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME, "new-name")).willReturn(TAG_NODE_REF);
|
||||
given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT));
|
||||
given(taggingServiceMock.findCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME)).willReturn(3L);
|
||||
|
||||
Tag tag = objectUnderTest.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, suppliedTag, parametersMock);
|
||||
|
||||
Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag("new-name").count(3L).create();
|
||||
assertEquals("Unexpected return value", expected, tag);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTag()
|
||||
{
|
||||
Tag tag = objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, parametersMock);
|
||||
|
||||
Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).create();
|
||||
assertEquals("Unexpected tag returned", expected, tag);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTagWithCount()
|
||||
{
|
||||
given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT));
|
||||
given(taggingServiceMock.findCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME)).willReturn(0L);
|
||||
|
||||
Tag tag = objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, parametersMock);
|
||||
|
||||
Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).count(0L).create();
|
||||
assertEquals("Unexpected tag returned", expected, tag);
|
||||
}
|
||||
|
||||
private static List<Pair<String, NodeRef>> createTagAndNodeRefPairs(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream()
|
||||
.map(tagName -> createPair(tagName, new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName))))
|
||||
.collect(toList());
|
||||
.map(tagName -> createPair(tagName, new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName))))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Pair<String, NodeRef> createPair(final String tagName, final NodeRef nodeRef)
|
||||
@@ -704,12 +280,12 @@ public class TagsImplTest
|
||||
|
||||
private static List<Tag> createTags(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream().map(TagsImplTest::createTag).collect(toList());
|
||||
return tagNames.stream().map(TagsImplTest::createTag).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static List<Tag> createTagsWithNodeRefs(final List<String> tagNames)
|
||||
{
|
||||
return tagNames.stream().map(TagsImplTest::createTagWithNodeRef).collect(toList());
|
||||
return tagNames.stream().map(TagsImplTest::createTagWithNodeRef).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Tag createTag(final String tagName)
|
||||
@@ -722,7 +298,7 @@ public class TagsImplTest
|
||||
private static Tag createTagWithNodeRef(final String tagName)
|
||||
{
|
||||
return Tag.builder()
|
||||
.nodeRef(new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName)))
|
||||
.nodeRef(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID.concat("-").concat(tagName)))
|
||||
.tag(tagName)
|
||||
.create();
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class RestRuleModelMapperTest
|
||||
// when
|
||||
final org.alfresco.service.cmr.rule.Rule actualRuleModel = objectUnderTest.toServiceModel(rule);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(RULE_ID);
|
||||
then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(actionMapperMock).should().toServiceModel(List.of(action));
|
||||
then(actionMapperMock).shouldHaveNoMoreInteractions();
|
||||
|
||||
@@ -275,7 +275,7 @@ public class RestRuleSimpleConditionModelMapperTest
|
||||
{
|
||||
final SimpleCondition simpleCondition = createSimpleCondition(PARAM_CATEGORY);
|
||||
final NodeRef defaultNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARAMETER_DEFAULT);
|
||||
given(nodesMock.validateOrLookupNode(PARAMETER_DEFAULT)).willReturn(defaultNodeRef);
|
||||
given(nodesMock.validateOrLookupNode(PARAMETER_DEFAULT, null)).willReturn(defaultNodeRef);
|
||||
|
||||
// when
|
||||
final ActionCondition actualActionCondition = objectUnderTest.toServiceModel(simpleCondition);
|
||||
|
||||
@@ -44,6 +44,7 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
|
||||
import org.alfresco.repo.action.executer.CheckInActionExecuter;
|
||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
|
||||
@@ -128,8 +129,8 @@ public class ActionParameterConverterTest
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
given(nodes.validateOrLookupNode(DUMMY_FOLDER_NODE_ID)).willReturn(DUMMY_FOLDER_NODE);
|
||||
given(nodes.validateOrLookupNode(DUMMY_SCRIPT_NODE_ID)).willReturn(DUMMY_SCRIPT_NODE);
|
||||
given(nodes.validateOrLookupNode(DUMMY_FOLDER_NODE_ID, null)).willReturn(DUMMY_FOLDER_NODE);
|
||||
given(nodes.validateOrLookupNode(DUMMY_SCRIPT_NODE_ID, null)).willReturn(DUMMY_SCRIPT_NODE);
|
||||
given(permissionService.hasReadPermission(DUMMY_FOLDER_NODE)).willReturn(ALLOWED);
|
||||
given(permissionService.hasReadPermission(DUMMY_SCRIPT_NODE)).willReturn(ALLOWED);
|
||||
}
|
||||
@@ -597,7 +598,7 @@ public class ActionParameterConverterTest
|
||||
String permissionDeniedNodeId = "permission://denied/node";
|
||||
final Map<String, Serializable> params = Map.of(PARAM_DESTINATION_FOLDER, permissionDeniedNodeId);
|
||||
NodeRef permissionDeniedNode = new NodeRef(permissionDeniedNodeId);
|
||||
given(nodes.validateOrLookupNode(permissionDeniedNodeId)).willReturn(permissionDeniedNode);
|
||||
given(nodes.validateOrLookupNode(permissionDeniedNodeId, null)).willReturn(permissionDeniedNode);
|
||||
given(permissionService.hasReadPermission(permissionDeniedNode)).willReturn(DENIED);
|
||||
|
||||
given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
|
||||
|
||||
@@ -101,7 +101,7 @@ public class NodeValidatorTest
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
MockitoAnnotations.openMocks(this);
|
||||
given(nodesMock.validateOrLookupNode(FOLDER_NODE_ID)).willReturn(folderNodeRef);
|
||||
given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
|
||||
given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
|
||||
given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
|
||||
given(nodesMock.nodeMatches(any(), any(), any())).willReturn(true);
|
||||
@@ -115,7 +115,7 @@ public class NodeValidatorTest
|
||||
// when
|
||||
final NodeRef nodeRef = nodeValidator.validateFolderNode(FOLDER_NODE_ID, false);
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID);
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
|
||||
then(nodesMock).should().nodeMatches(folderNodeRef, Set.of(TYPE_FOLDER), null);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(permissionServiceMock).should().hasReadPermission(folderNodeRef);
|
||||
@@ -128,13 +128,13 @@ public class NodeValidatorTest
|
||||
@Test
|
||||
public void testValidateFolderNode_notExistingFolder()
|
||||
{
|
||||
given(nodesMock.validateOrLookupNode(FOLDER_NODE_ID)).willThrow(new EntityNotFoundException(FOLDER_NODE_ID));
|
||||
given(nodesMock.validateOrLookupNode(any(), any())).willThrow(new EntityNotFoundException(FOLDER_NODE_ID));
|
||||
|
||||
//when
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
|
||||
() -> nodeValidator.validateFolderNode(FOLDER_NODE_ID, false));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID);
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleServiceMock).shouldHaveNoInteractions();
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public class NodeValidatorTest
|
||||
assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
|
||||
() -> nodeValidator.validateFolderNode(FOLDER_NODE_ID, false));
|
||||
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID);
|
||||
then(nodesMock).should().validateOrLookupNode(FOLDER_NODE_ID, null);
|
||||
then(nodesMock).should().nodeMatches(folderNodeRef, Set.of(TYPE_FOLDER), null);
|
||||
then(nodesMock).shouldHaveNoMoreInteractions();
|
||||
then(ruleServiceMock).shouldHaveNoInteractions();
|
||||
@@ -431,12 +431,11 @@ public class NodeValidatorTest
|
||||
then(ruleServiceMock).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
|
||||
private void resetNodesMock()
|
||||
{
|
||||
private void resetNodesMock() {
|
||||
reset(nodesMock);
|
||||
given(nodesMock.validateOrLookupNode(FOLDER_NODE_ID)).willReturn(folderNodeRef);
|
||||
given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
|
||||
given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
|
||||
given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
|
||||
given(nodesMock.nodeMatches(ruleSetNodeRef, Set.of(ContentModel.TYPE_SYSTEM_FOLDER), null)).willReturn(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,10 @@ import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyBoolean;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.notNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -184,7 +186,7 @@ public class ResultMapperTests
|
||||
when(sr.getVersionService()).thenReturn(versionService);
|
||||
when(sr.getNodeService()).thenReturn(nodeService);
|
||||
|
||||
when(nodes.validateOrLookupNode(nullable(String.class))).thenAnswer(invocation ->
|
||||
when(nodes.validateOrLookupNode(nullable(String.class), nullable(String.class))).thenAnswer(invocation ->
|
||||
{
|
||||
Object[] args = invocation.getArguments();
|
||||
String aNode = (String)args[0];
|
||||
|
||||
@@ -529,7 +529,7 @@ public class AuthenticationsTest extends AbstractSingleNetworkSiteTest
|
||||
InterceptingIdentityRemoteUserMapper interceptingRemoteUserMapper = new InterceptingIdentityRemoteUserMapper();
|
||||
interceptingRemoteUserMapper.setActive(true);
|
||||
interceptingRemoteUserMapper.setPersonService(personServiceLocal);
|
||||
interceptingRemoteUserMapper.setIdentityServiceFacade(null);
|
||||
interceptingRemoteUserMapper.setIdentityServiceDeployment(null);
|
||||
interceptingRemoteUserMapper.setUserIdToReturn(user2);
|
||||
remoteUserMapper = interceptingRemoteUserMapper;
|
||||
}
|
||||
|
||||
@@ -734,6 +734,195 @@ public class SharedLinkApiTest extends AbstractBaseApiTest
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests shared links to file (content) in a multi-tenant system.
|
||||
*
|
||||
* <p>POST:</p>
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links}
|
||||
*
|
||||
* <p>DELETE:</p>
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>}
|
||||
*
|
||||
* <p>GET:</p>
|
||||
* The following do not require authentication
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>}
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>/content}
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>/renditions}
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>/renditions/<renditionId>}
|
||||
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/shared-links/<sharedId>/renditions/<renditionId>/content}
|
||||
*
|
||||
*/
|
||||
// TODO now covered by testSharedLinkCreateGetDelete ? (since base class now uses tenant context by default)
|
||||
@Test
|
||||
public void testSharedLinkCreateGetDelete_MultiTenant() throws Exception
|
||||
{
|
||||
// As user1
|
||||
setRequestContext(user1);
|
||||
|
||||
String docLibNodeId = getSiteContainerNodeId(tSiteId, "documentLibrary");
|
||||
|
||||
String folderName = "folder" + System.currentTimeMillis() + "_1";
|
||||
String folderId = createFolder(docLibNodeId, folderName, null).getId();
|
||||
|
||||
// create doc d1 - pdf
|
||||
String fileName1 = "quick" + RUNID + "_1.pdf";
|
||||
File file1 = getResourceFile("quick.pdf");
|
||||
|
||||
byte[] file1_originalBytes = Files.readAllBytes(Paths.get(file1.getAbsolutePath()));
|
||||
|
||||
String file1_MimeType = MimetypeMap.MIMETYPE_PDF;
|
||||
|
||||
MultiPartBuilder.MultiPartRequest reqBody = MultiPartBuilder.create()
|
||||
.setFileData(new MultiPartBuilder.FileData(fileName1, file1, file1_MimeType))
|
||||
.build();
|
||||
|
||||
HttpResponse response = post(getNodeChildrenUrl(folderId), reqBody.getBody(), null, reqBody.getContentType(), 201);
|
||||
Document doc1 = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
|
||||
String d1Id = doc1.getId();
|
||||
assertNotNull(d1Id);
|
||||
|
||||
// create shared link to document 1
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("nodeId", d1Id);
|
||||
response = post(URL_SHARED_LINKS, toJsonAsStringNonNull(body), 201);
|
||||
QuickShareLink resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
String shared1Id = resp.getId();
|
||||
assertNotNull(shared1Id);
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
assertEquals(fileName1, resp.getName());
|
||||
assertEquals(file1_MimeType, resp.getContent().getMimeType());
|
||||
assertEquals(user1, resp.getSharedByUser().getId());
|
||||
|
||||
// allowable operations not included - no params
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id, null, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
assertNull(resp.getAllowableOperations());
|
||||
|
||||
setRequestContext(null);
|
||||
|
||||
// unauth access to get shared link info
|
||||
Map<String, String> params = Collections.singletonMap("include", "allowableOperations"); // note: this will be ignore for unauth access
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id, params, 200);
|
||||
resp = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), QuickShareLink.class);
|
||||
assertEquals(shared1Id, resp.getId());
|
||||
assertEquals(fileName1, resp.getName());
|
||||
assertEquals(d1Id, resp.getNodeId());
|
||||
assertNull(resp.getAllowableOperations()); // include is ignored
|
||||
assertNull(resp.getAllowableOperationsOnTarget()); // include is ignored
|
||||
|
||||
|
||||
// unauth access to file 1 content (via shared link)
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id + "/content", null, 200);
|
||||
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
|
||||
Map<String, String> responseHeaders = response.getHeaders();
|
||||
assertNotNull(responseHeaders);
|
||||
assertEquals(file1_MimeType + ";charset=utf-8", responseHeaders.get("Content-Type"));
|
||||
assertNotNull(responseHeaders.get("Expires"));
|
||||
assertEquals("attachment; filename=\"" + fileName1 + "\"; filename*=UTF-8''" + fileName1 + "", responseHeaders.get("Content-Disposition"));
|
||||
String lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);
|
||||
assertNotNull(lastModifiedHeader);
|
||||
// Test 304 response
|
||||
Map<String, String> headers = Collections.singletonMap(IF_MODIFIED_SINCE_HEADER, lastModifiedHeader);
|
||||
getSingle(URL_SHARED_LINKS, shared1Id + "/content", null, headers, 304);
|
||||
|
||||
// unauth access to file 1 content (via shared link) - without Content-Disposition header (attachment=false)
|
||||
params = new HashMap<>();
|
||||
params.put("attachment", "false");
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id + "/content", params, 200);
|
||||
assertArrayEquals(file1_originalBytes, response.getResponseAsBytes());
|
||||
responseHeaders = response.getHeaders();
|
||||
assertNotNull(responseHeaders);
|
||||
assertEquals(file1_MimeType + ";charset=utf-8", responseHeaders.get("Content-Type"));
|
||||
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
|
||||
assertNotNull(responseHeaders.get("Expires"));
|
||||
assertNull(responseHeaders.get("Content-Disposition"));
|
||||
|
||||
// -ve shared link rendition tests
|
||||
{
|
||||
// -ve test - try to get non-existent rendition content
|
||||
getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/doclib/content", null, 404);
|
||||
|
||||
// -ve test - try to get unregistered rendition content
|
||||
getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/dummy/content", null, 404);
|
||||
}
|
||||
|
||||
// unauth access to get rendition info for a shared link (available => CREATED rendition only)
|
||||
// -ve shared link rendition tests
|
||||
{
|
||||
// -ve test - try to get not created rendition for the given shared link
|
||||
getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/doclib", null, 404);
|
||||
|
||||
// -ve test - try to get unregistered rendition
|
||||
getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/dummy", null, 404);
|
||||
}
|
||||
|
||||
// unauth access to get shared link renditions info (available => CREATED renditions only)
|
||||
response = getAll(URL_SHARED_LINKS + "/" + shared1Id + "/renditions", null, 200);
|
||||
List<Rendition> renditions = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Rendition.class);
|
||||
assertEquals(0, renditions.size());
|
||||
|
||||
// create rendition of pdf doc - note: for some reason create rendition of txt doc fail on build m/c (TBC) ?
|
||||
setRequestContext(user1);
|
||||
|
||||
Rendition rendition = createAndGetRendition(d1Id, "doclib");
|
||||
assertNotNull(rendition);
|
||||
assertEquals(Rendition.RenditionStatus.CREATED, rendition.getStatus());
|
||||
|
||||
setRequestContext(null);
|
||||
|
||||
// unauth access to get shared link renditions info (available => CREATED renditions only)
|
||||
response = getAll(URL_SHARED_LINKS + "/" + shared1Id + "/renditions", null, 200);
|
||||
renditions = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Rendition.class);
|
||||
assertEquals(1, renditions.size());
|
||||
assertEquals(Rendition.RenditionStatus.CREATED, renditions.get(0).getStatus());
|
||||
assertEquals("doclib", renditions.get(0).getId());
|
||||
|
||||
// unauth access to get rendition info for a shared link (available => CREATED rendition only)
|
||||
{
|
||||
// get a created rendition for the given shared link
|
||||
getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/doclib", null, 200);
|
||||
}
|
||||
|
||||
// unauth access to get shared link file rendition content
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/doclib/content", null, 200);
|
||||
assertTrue(response.getResponseAsBytes().length > 0);
|
||||
responseHeaders = response.getHeaders();
|
||||
assertNotNull(responseHeaders);
|
||||
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=utf-8", responseHeaders.get("Content-Type"));
|
||||
assertNotNull(responseHeaders.get(LAST_MODIFIED_HEADER));
|
||||
assertNotNull(responseHeaders.get("Expires"));
|
||||
String docName = "doclib";
|
||||
assertEquals("attachment; filename=\"" + docName + "\"; filename*=UTF-8''" + docName + "", responseHeaders.get("Content-Disposition"));
|
||||
|
||||
// unauth access to get shared link file rendition content - without Content-Disposition header (attachment=false)
|
||||
params = new HashMap<>();
|
||||
params.put("attachment", "false");
|
||||
response = getSingle(QuickShareLinkEntityResource.class, shared1Id + "/renditions/doclib/content", params, 200);
|
||||
assertTrue(response.getResponseAsBytes().length > 0);
|
||||
responseHeaders = response.getHeaders();
|
||||
assertNotNull(responseHeaders);
|
||||
assertEquals(MimetypeMap.MIMETYPE_IMAGE_PNG + ";charset=utf-8", responseHeaders.get("Content-Type"));
|
||||
assertNotNull(responseHeaders.get("Expires"));
|
||||
assertNull(responseHeaders.get("Content-Disposition"));
|
||||
lastModifiedHeader = responseHeaders.get(LAST_MODIFIED_HEADER);
|
||||
assertNotNull(lastModifiedHeader);
|
||||
// Test 304 response
|
||||
headers = Collections.singletonMap(IF_MODIFIED_SINCE_HEADER, lastModifiedHeader);
|
||||
getSingle(URL_SHARED_LINKS, shared1Id + "/renditions/doclib/content", null, headers, 304);
|
||||
|
||||
// -ve test - userTwoN1 cannot delete shared link
|
||||
setRequestContext(user2);
|
||||
deleteSharedLink(shared1Id, 403);
|
||||
|
||||
// -ve test - unauthenticated
|
||||
setRequestContext(null);
|
||||
deleteSharedLink(shared1Id, 401);
|
||||
|
||||
// delete shared link
|
||||
setRequestContext(user1);
|
||||
deleteSharedLink(shared1Id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests shared links to file with expiry date.
|
||||
* <p>POST:</p>
|
||||
|
||||
@@ -1,666 +0,0 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 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.framework.resource.parameters.where;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.rest.antlr.WhereClauseParser;
|
||||
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
|
||||
import org.alfresco.rest.workflow.api.impl.MapBasedQueryWalker;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests verifying {@link QueryHelper.QueryResolver} functionality based on {@link BasicQueryWalker}.
|
||||
*/
|
||||
public class QueryResolverTest
|
||||
{
|
||||
private final RecognizedParamsExtractor queryExtractor = new RecognizedParamsExtractor() {};
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, true)).isFalse();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, false)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_greaterThan()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName > testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHAN, false)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_greaterThanOrEquals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName >= testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHANOREQUALS, false)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_lessThan()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName < testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.LESSTHAN, false)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_lessThanOrEquals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName <= testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.LESSTHANOREQUALS, false)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_between()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName BETWEEN (testValue, testValue2))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.BETWEEN, false)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_in()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName IN (testValue, testValue2))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.IN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.IN, false)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_matches()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName MATCHES ('*Value'))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.MATCHES, false)).containsOnly("*Value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_exists()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(EXISTS (propName))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EXISTS, false)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notEquals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName=testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, true)).isTrue();
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, true)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, true)).isFalse();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, true)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notGreaterThan()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName > testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHAN, true)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notGreaterThanOrEquals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName >= testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHANOREQUALS, true)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notLessThan()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName < testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.LESSTHAN, true)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notLessThanOrEquals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName <= testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHANOREQUALS, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.LESSTHANOREQUALS, true)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notBetween()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName BETWEEN (testValue, testValue2))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.BETWEEN, true)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notIn()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName IN (testValue, testValue2))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.IN, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.IN, true)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notMatches()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName MATCHES ('*Value'))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.MATCHES, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.MATCHES, true)).containsOnly("*Value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_notExists()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT EXISTS (propName))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, true)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EXISTS, true)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_propertyNotExpected()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND differentName>18)");
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> QueryHelper.resolve(query).getProperty("differentName"));
|
||||
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_propertyNotExpectedUsingLenientApproach()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND differentName>18)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).leniently().getProperty("differentName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, true)).isFalse();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, false)).isNull();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, true)).isNull();
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHAN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHAN, false)).containsOnly("18");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_propertyNotPresentUsingLenientApproach()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue)");
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> QueryHelper.resolve(query).getProperty("differentName"));
|
||||
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_slashInPropertyName()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(EXISTS (prop/name/with/slashes))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("prop/name/with/slashes");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EXISTS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EXISTS, false)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_propertyBetweenDates()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName BETWEEN ('2012-01-01', '2012-12-31'))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.BETWEEN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.BETWEEN, false)).containsOnly("2012-01-01", "2012-12-31");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_singlePropertyGreaterThanOrEqualsAndLessThan()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName >= 18 AND propName < 65)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper.resolve(query).getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.GREATERTHANOREQUALS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.GREATERTHANOREQUALS, false)).containsOnly("18");
|
||||
assertThat(property.containsType(WhereClauseParser.LESSTHAN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.LESSTHAN, false)).containsOnly("65");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_onePropertyGreaterThanAndSecondPropertyNotMatches()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName1 > 20 AND NOT propName2 MATCHES ('external*'))");
|
||||
|
||||
//when
|
||||
final List<WhereProperty> property = QueryHelper.resolve(query).getProperties("propName1", "propName2");
|
||||
|
||||
assertThat(property.get(0).containsType(WhereClauseParser.GREATERTHAN, false)).isTrue();
|
||||
assertThat(property.get(0).getExpectedValuesFor(WhereClauseParser.GREATERTHAN, false)).containsOnly("20");
|
||||
assertThat(property.get(1).containsType(WhereClauseParser.MATCHES, true)).isTrue();
|
||||
assertThat(property.get(1).getExpectedValuesFor(WhereClauseParser.MATCHES, true)).containsOnly("external*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_negationsForbidden()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(NOT propName=testValue)");
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> QueryHelper.resolve(query).withoutNegations().getProperty("propName"));
|
||||
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_withoutNegations()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty actualProperty = QueryHelper.resolve(query).withoutNegations().getProperty("propName");
|
||||
|
||||
assertThat(actualProperty.containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(actualProperty.containsType(WhereClauseParser.EQUALS, true)).isFalse();
|
||||
assertThat(actualProperty.getExpectedValuesFor(WhereClauseParser.EQUALS).onlyNegated()).isNull();
|
||||
assertThat(actualProperty.getExpectedValuesFor(WhereClauseParser.EQUALS).skipNegated()).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_orNotAllowed()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue OR propName BETWEEN (testValue2, testValue3))");
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> QueryHelper.resolve(query).getProperty("propName"));
|
||||
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_orAllowedInFavorOfAnd()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue OR propName=testValue2)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.usingOrOperator()
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, false)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_usingCustomQueryWalker()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue)");
|
||||
|
||||
//when
|
||||
final Collection<String> propertyValues = QueryHelper
|
||||
.resolve(query)
|
||||
.usingWalker(new MapBasedQueryWalker(Set.of("propName"), null))
|
||||
.getProperty("propName", WhereClauseParser.EQUALS, false);
|
||||
|
||||
assertThat(propertyValues).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_usingCustomBasicQueryWalkerExtension()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue OR propName=testValue2)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.usingWalker(new BasicQueryWalker("propName")
|
||||
{
|
||||
@Override
|
||||
public void or() {}
|
||||
@Override
|
||||
public void and() {throw UNSUPPORTED;}
|
||||
})
|
||||
.withoutNegations()
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesFor(WhereClauseParser.EQUALS, false)).containsOnly("testValue", "testValue2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equalsAndInNotAllowedTogether()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND propName IN (testValue2, testValue3))");
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> QueryHelper.resolve(query).getProperty("propName"));
|
||||
|
||||
assertThat(actualException).isInstanceOf(InvalidQueryException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equalsOrInAllowedTogether()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue OR propName IN (testValue2, testValue3))");
|
||||
|
||||
//when
|
||||
final WhereProperty whereProperty = QueryHelper.resolve(query).usingOrOperator().getProperty("propName");
|
||||
|
||||
assertThat(whereProperty).isNotNull();
|
||||
assertThat(whereProperty.getExpectedValuesForAllOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated())
|
||||
.isEqualTo(Map.of(WhereClauseParser.EQUALS, Set.of("testValue"), WhereClauseParser.IN, Set.of("testValue2", "testValue3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equalsAndInAllowedTogetherWithDifferentProperties()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND propName2 IN (testValue2, testValue3))");
|
||||
|
||||
//when
|
||||
final List<WhereProperty> properties = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperties("propName", "propName2");
|
||||
|
||||
assertThat(properties.get(0).containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(properties.get(0).containsType(WhereClauseParser.IN, false)).isFalse();
|
||||
assertThat(properties.get(0).getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().get(WhereClauseParser.EQUALS)).containsOnly("testValue");
|
||||
assertThat(properties.get(0).getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().containsKey(WhereClauseParser.IN)).isFalse();
|
||||
assertThat(properties.get(1).containsType(WhereClauseParser.EQUALS, false)).isFalse();
|
||||
assertThat(properties.get(1).containsType(WhereClauseParser.IN, false)).isTrue();
|
||||
assertThat(properties.get(1).getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().containsKey(WhereClauseParser.EQUALS)).isFalse();
|
||||
assertThat(properties.get(1).getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().get(WhereClauseParser.IN)).containsOnly("testValue2", "testValue3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equalsAndInAllowedAlternately_equals()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue)");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isTrue();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, false)).isFalse();
|
||||
assertThat(property.getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().get(WhereClauseParser.EQUALS)).containsOnly("testValue");
|
||||
assertThat(property.getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().containsKey(WhereClauseParser.IN)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_equalsAndInAllowedAlternately_in()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName IN (testValue))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.containsType(WhereClauseParser.EQUALS, false)).isFalse();
|
||||
assertThat(property.containsType(WhereClauseParser.IN, false)).isTrue();
|
||||
assertThat(property.getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().containsKey(WhereClauseParser.EQUALS)).isFalse();
|
||||
assertThat(property.getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.IN).skipNegated().get(WhereClauseParser.IN)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_missingEqualsClauseType()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName MATCHES (testValue))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThatExceptionOfType(InvalidQueryException.class)
|
||||
.isThrownBy(() -> property.getExpectedValuesForAllOf(WhereClauseParser.EQUALS, WhereClauseParser.MATCHES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_ignoreUnexpectedClauseType()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND propName MATCHES (testValue))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.getExpectedValuesForAllOf(WhereClauseParser.EQUALS).skipNegated(WhereClauseParser.EQUALS)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_complexAndQuery()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(a=v1 AND b>18 AND b<=65 AND NOT c BETWEEN ('2012-01-01','2012-12-31') AND d IN (v1, v2) AND e MATCHES ('*@mail.com') AND EXISTS (f/g))");
|
||||
|
||||
//when
|
||||
final List<WhereProperty> properties = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperties("a", "b", "c", "d", "e", "f/g");
|
||||
|
||||
assertThat(properties).hasSize(6);
|
||||
assertThat(properties.get(0).getExpectedValuesFor(WhereProperty.ClauseType.EQUALS)).containsOnly("v1");
|
||||
assertThat(properties.get(1).containsAllTypes(WhereProperty.ClauseType.GREATER_THAN, WhereProperty.ClauseType.LESS_THAN_OR_EQUALS)).isTrue();
|
||||
assertThat(properties.get(1).getExpectedValuesFor(WhereProperty.ClauseType.GREATER_THAN)).containsOnly("18");
|
||||
assertThat(properties.get(1).getExpectedValuesFor(WhereProperty.ClauseType.LESS_THAN_OR_EQUALS)).containsOnly("65");
|
||||
assertThat(properties.get(2).getExpectedValuesFor(WhereProperty.ClauseType.NOT_BETWEEN)).containsOnly("2012-01-01", "2012-12-31");
|
||||
assertThat(properties.get(3).getExpectedValuesFor(WhereProperty.ClauseType.IN)).containsOnly("v1", "v2");
|
||||
assertThat(properties.get(4).getExpectedValuesFor(WhereProperty.ClauseType.MATCHES)).containsOnly("*@mail.com");
|
||||
assertThat(properties.get(5).containsType(WhereProperty.ClauseType.EXISTS)).isTrue();
|
||||
assertThat(properties.get(5).getExpectedValuesFor(WhereProperty.ClauseType.EXISTS)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_complexOrQuery()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(a=v1 OR b>18 OR b<=65 OR NOT c BETWEEN ('2012-01-01','2012-12-31') OR d IN (v1, v2) OR e MATCHES ('*@mail.com') OR EXISTS (f/g))");
|
||||
|
||||
//when
|
||||
final List<WhereProperty> properties = QueryHelper
|
||||
.resolve(query)
|
||||
.usingOrOperator()
|
||||
.getProperties("a", "b", "c", "d", "e", "f/g");
|
||||
|
||||
assertThat(properties).hasSize(6);
|
||||
assertThat(properties.get(0).getExpectedValuesFor(WhereProperty.ClauseType.EQUALS)).containsOnly("v1");
|
||||
assertThat(properties.get(1).containsAllTypes(WhereProperty.ClauseType.GREATER_THAN, WhereProperty.ClauseType.LESS_THAN_OR_EQUALS)).isTrue();
|
||||
assertThat(properties.get(1).getExpectedValuesFor(WhereProperty.ClauseType.GREATER_THAN)).containsOnly("18");
|
||||
assertThat(properties.get(1).getExpectedValuesFor(WhereProperty.ClauseType.LESS_THAN_OR_EQUALS)).containsOnly("65");
|
||||
assertThat(properties.get(2).getExpectedValuesFor(WhereProperty.ClauseType.NOT_BETWEEN)).containsOnly("2012-01-01", "2012-12-31");
|
||||
assertThat(properties.get(3).getExpectedValuesFor(WhereProperty.ClauseType.IN)).containsOnly("v1", "v2");
|
||||
assertThat(properties.get(4).getExpectedValuesFor(WhereProperty.ClauseType.MATCHES)).containsOnly("*@mail.com");
|
||||
assertThat(properties.get(5).containsType(WhereProperty.ClauseType.EXISTS)).isTrue();
|
||||
assertThat(properties.get(5).getExpectedValuesFor(WhereProperty.ClauseType.EXISTS)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_clauseTypeOptional()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName MATCHES (testValue))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThat(property.getExpectedValuesForAnyOf(WhereClauseParser.EQUALS, WhereClauseParser.MATCHES).skipNegated(WhereClauseParser.MATCHES)).containsOnly("testValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_optionalClauseTypesNotPresent()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName=testValue AND propName MATCHES (testValue))");
|
||||
|
||||
//when
|
||||
final WhereProperty property = QueryHelper
|
||||
.resolve(query)
|
||||
.getProperty("propName");
|
||||
|
||||
assertThatExceptionOfType(InvalidQueryException.class)
|
||||
.isThrownBy(() -> property.getExpectedValuesForAnyOf(WhereClauseParser.IN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveQuery_matchesOrMatchesAllowed()
|
||||
{
|
||||
final Query query = queryExtractor.getWhereClause("(propName MATCHES ('test*') OR propName MATCHES ('*value*'))");
|
||||
|
||||
//when
|
||||
final Collection<String> expectedValues = QueryHelper
|
||||
.resolve(query)
|
||||
.usingOrOperator()
|
||||
.getProperty("propName")
|
||||
.getExpectedValuesFor(WhereClauseParser.MATCHES)
|
||||
.skipNegated();
|
||||
|
||||
assertThat(expectedValues).containsOnly("test*", "*value*");
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.1.0.133</version>
|
||||
<version>20.101-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -119,14 +119,10 @@
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ibm.icu</groupId>
|
||||
<artifactId>icu4j</artifactId>
|
||||
<version>73.1</version>
|
||||
<version>72.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
@@ -375,24 +371,30 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.woodstox</groupId>
|
||||
<artifactId>woodstox-core</artifactId>
|
||||
<version>6.5.1</version>
|
||||
<version>6.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- GData -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
<groupId>com.google.gdata</groupId>
|
||||
<artifactId>gdata-core-1.0</artifactId>
|
||||
<version>1.47.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.gdata</groupId>
|
||||
<artifactId>gdata-media-1.0</artifactId>
|
||||
<version>1.47.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-resource-server</artifactId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${dependency.spring-security.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
@@ -554,6 +556,80 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Keycloak dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-servlet-adapter-spi</artifactId>
|
||||
<version>${dependency.keycloak.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- required by keycloak -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${dependency.jboss.logging.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Events dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
@@ -736,7 +812,7 @@
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.9.19</version>
|
||||
<version>1.9.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
@@ -798,10 +874,6 @@
|
||||
<artifactId>reflections</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.email.server;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -37,7 +37,10 @@ import org.alfresco.service.cmr.email.EmailMessageException;
|
||||
import org.alfresco.service.cmr.email.EmailService;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Base implementation of an email server.
|
||||
@@ -59,13 +62,13 @@ public abstract class EmailServer extends AbstractLifecycleBean
|
||||
private boolean requireTLS = false;
|
||||
private boolean authenticate = false;
|
||||
|
||||
private EmailService emailService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private EmailService emailService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private String unknownUser;
|
||||
|
||||
protected EmailServer()
|
||||
{
|
||||
this.enabled = false;
|
||||
|
||||
protected EmailServer()
|
||||
{
|
||||
this.enabled = false;
|
||||
this.port = 25;
|
||||
this.domain = null;
|
||||
this.maxConnections = 3;
|
||||
@@ -298,6 +301,60 @@ public abstract class EmailServer extends AbstractLifecycleBean
|
||||
}
|
||||
}
|
||||
|
||||
private static volatile Boolean stop = false;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if (args.length == 0)
|
||||
{
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
try (AbstractApplicationContext context = new ClassPathXmlApplicationContext(args))
|
||||
{
|
||||
if (!context.containsBean("emailServer"))
|
||||
{
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
public void run()
|
||||
{
|
||||
stop = true;
|
||||
synchronized (stop)
|
||||
{
|
||||
stop.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
System.out.println("Use Ctrl-C to shutdown EmailServer");
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
synchronized (stop)
|
||||
{
|
||||
stop.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (BeansException e)
|
||||
{
|
||||
System.err.println("Error creating context: " + e);
|
||||
usage();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void usage()
|
||||
{
|
||||
System.err.println("Use: EmailServer configLocation1, configLocation2, ...");
|
||||
System.err.println("\t configLocation - spring xml configs with EmailServer related beans (emailServer, emailServerConfiguration, emailService)");
|
||||
}
|
||||
|
||||
/**
|
||||
* authenticate with a user/password
|
||||
* @param userName
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.email.server.impl.subetha;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -416,12 +417,29 @@ public class SubethaEmailMessage implements EmailMessage
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setRmiRegistry(String rmiRegistryHost, int rmiRegistryPort)
|
||||
{
|
||||
if (body instanceof SubethaEmailMessagePart)
|
||||
{
|
||||
((SubethaEmailMessagePart) body).setRmiRegistry(rmiRegistryHost, rmiRegistryPort);
|
||||
}
|
||||
|
||||
for (EmailMessagePart attachment : attachments)
|
||||
{
|
||||
if (attachment instanceof SubethaEmailMessagePart)
|
||||
{
|
||||
((SubethaEmailMessagePart) attachment).setRmiRegistry(rmiRegistryHost, rmiRegistryPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getCC()
|
||||
{
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
public String getFrom()
|
||||
{
|
||||
return from;
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.email.server.impl.subetha;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -36,6 +39,7 @@ import javax.mail.Part;
|
||||
import org.alfresco.service.cmr.email.EmailMessageException;
|
||||
import org.alfresco.service.cmr.email.EmailMessagePart;
|
||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||
import org.alfresco.util.remote.RemotableInputStream;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -60,6 +64,9 @@ public class SubethaEmailMessagePart implements EmailMessagePart
|
||||
private String contentType;
|
||||
private InputStream contentInputStream;
|
||||
|
||||
private String rmiRegistryHost;
|
||||
private int rmiRegistryPort;
|
||||
|
||||
protected SubethaEmailMessagePart()
|
||||
{
|
||||
super();
|
||||
@@ -138,4 +145,20 @@ public class SubethaEmailMessagePart implements EmailMessagePart
|
||||
}
|
||||
|
||||
|
||||
public void setRmiRegistry(String rmiRegistryHost, int rmiRegistryPort)
|
||||
{
|
||||
this.rmiRegistryHost = rmiRegistryHost;
|
||||
this.rmiRegistryPort = rmiRegistryPort;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException
|
||||
{
|
||||
contentInputStream = new RemotableInputStream(rmiRegistryHost, rmiRegistryPort, contentInputStream);
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
package org.alfresco.repo.content.transform;
|
||||
|
||||
import org.alfresco.httpclient.HttpClientConfig;
|
||||
import org.alfresco.repo.content.metadata.AsynchronousExtractor;
|
||||
import org.alfresco.repo.rendition2.RenditionDefinition2;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
@@ -61,12 +60,11 @@ public class LocalTransformImpl extends AbstractLocalTransform
|
||||
boolean retryTransformOnDifferentMimeType,
|
||||
Set<TransformOption> transformsTransformOptions,
|
||||
LocalTransformServiceRegistry localTransformServiceRegistry, String baseUrl,
|
||||
HttpClientConfig httpClientConfig,
|
||||
int startupRetryPeriodSeconds)
|
||||
{
|
||||
super(name, transformerDebug, mimetypeService, strictMimeTypeCheck, strictMimetypeExceptions,
|
||||
retryTransformOnDifferentMimeType, transformsTransformOptions, localTransformServiceRegistry);
|
||||
remoteTransformerClient = new RemoteTransformerClient(name, baseUrl, httpClientConfig);
|
||||
remoteTransformerClient = new RemoteTransformerClient(name, baseUrl);
|
||||
remoteTransformerClient.setStartupRetryPeriodSeconds(startupRetryPeriodSeconds);
|
||||
|
||||
checkAvailability();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2019 - 2023 Alfresco Software Limited
|
||||
* Copyright (C) 2019 - 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
|
||||
@@ -35,8 +35,6 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.httpclient.HttpClient4Factory;
|
||||
import org.alfresco.httpclient.HttpClientConfig;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.transform.config.CoreFunction;
|
||||
import org.alfresco.transform.config.TransformOptionGroup;
|
||||
@@ -79,17 +77,6 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
|
||||
private boolean strictMimeTypeCheck;
|
||||
private Map<String, Set<String>> strictMimetypeExceptions;
|
||||
private boolean retryTransformOnDifferentMimeType;
|
||||
private HttpClientConfig httpClientConfig;
|
||||
|
||||
public HttpClientConfig getHttpClientConfig()
|
||||
{
|
||||
return httpClientConfig;
|
||||
}
|
||||
|
||||
public void setHttpClientConfig(HttpClientConfig httpClientConfig)
|
||||
{
|
||||
this.httpClientConfig = httpClientConfig;
|
||||
}
|
||||
|
||||
public void setPipelineConfigDir(String pipelineConfigDir)
|
||||
{
|
||||
@@ -147,7 +134,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
|
||||
@Override
|
||||
public boolean readConfig() throws IOException
|
||||
{
|
||||
CombinedConfig combinedConfig = new CombinedConfig(getLog(), this, httpClientConfig);
|
||||
CombinedConfig combinedConfig = new CombinedConfig(getLog(), this);
|
||||
List<String> urls = getTEngineUrlsSortedByName();
|
||||
boolean successReadingConfig = combinedConfig.addRemoteConfig(urls, "T-Engine");
|
||||
successReadingConfig &= combinedConfig.addLocalConfig("alfresco/transforms");
|
||||
@@ -201,8 +188,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
|
||||
int startupRetryPeriodSeconds = getStartupRetryPeriodSeconds(name);
|
||||
localTransform = new LocalTransformImpl(name, transformerDebug, mimetypeService,
|
||||
strictMimeTypeCheck, strictMimetypeExceptions, retryTransformOnDifferentMimeType,
|
||||
transformsTransformOptions, this, baseUrl, httpClientConfig,
|
||||
startupRetryPeriodSeconds);
|
||||
transformsTransformOptions, this, baseUrl, startupRetryPeriodSeconds);
|
||||
}
|
||||
else if (isPipeline)
|
||||
{
|
||||
|
||||
@@ -30,8 +30,6 @@ import java.io.InputStream;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.httpclient.HttpClient4Factory;
|
||||
import org.alfresco.httpclient.HttpClientConfig;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.util.Pair;
|
||||
@@ -47,6 +45,7 @@ import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
/**
|
||||
@@ -58,8 +57,6 @@ import org.apache.http.util.EntityUtils;
|
||||
*/
|
||||
public class RemoteTransformerClient
|
||||
{
|
||||
private final HttpClientConfig httpClientConfig;
|
||||
|
||||
private final String name;
|
||||
private final String baseUrl;
|
||||
|
||||
@@ -73,11 +70,10 @@ public class RemoteTransformerClient
|
||||
// Only changed once on success. This is stored so it can always be returned.
|
||||
private Pair<Boolean, String> checkResult = new Pair<>(null, null);
|
||||
|
||||
public RemoteTransformerClient(String name, String baseUrl, HttpClientConfig httpClientConfig)
|
||||
public RemoteTransformerClient(String name, String baseUrl)
|
||||
{
|
||||
this.name = name;
|
||||
this.baseUrl = baseUrl == null || baseUrl.trim().isEmpty() ? null : baseUrl.trim();
|
||||
this.httpClientConfig = httpClientConfig;
|
||||
}
|
||||
|
||||
public void setStartupRetryPeriodSeconds(int startupRetryPeriodSeconds)
|
||||
@@ -133,7 +129,7 @@ public class RemoteTransformerClient
|
||||
|
||||
try
|
||||
{
|
||||
try (CloseableHttpClient httpclient = HttpClient4Factory.createHttpClient(httpClientConfig))
|
||||
try (CloseableHttpClient httpclient = HttpClients.createDefault())
|
||||
{
|
||||
try (CloseableHttpResponse response = execute(httpclient, httppost))
|
||||
{
|
||||
@@ -236,7 +232,7 @@ public class RemoteTransformerClient
|
||||
|
||||
try
|
||||
{
|
||||
try (CloseableHttpClient httpclient = HttpClient4Factory.createHttpClient(httpClientConfig))
|
||||
try (CloseableHttpClient httpclient = HttpClients.createDefault())
|
||||
{
|
||||
try (CloseableHttpResponse response = execute(httpclient, httpGet))
|
||||
{
|
||||
|
||||
@@ -23,225 +23,225 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support class for finding categories, finding root nodes for categories and creating root categories.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public final class Classification extends BaseScopableProcessorExtension
|
||||
{
|
||||
private ServiceRegistry services;
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
/**
|
||||
* Set the default store reference
|
||||
*
|
||||
* @param storeRef the default store reference
|
||||
*/
|
||||
public void setStoreUrl(String storeRef)
|
||||
{
|
||||
this.storeRef = new StoreRef(storeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
* @param services the service registry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the category nodes in a given classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getAllCategoryNodes(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getCategories(
|
||||
storeRef, createQName(aspect), CategoryService.Depth.ANY));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the aspects that define a classification.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getAllClassificationAspects()
|
||||
{
|
||||
Collection<QName> aspects = services.getCategoryService().getClassificationAspects();
|
||||
String[] answer = new String[aspects.size()];
|
||||
int i = 0;
|
||||
for (QName qname : aspects)
|
||||
{
|
||||
answer[i++] = qname.toPrefixString(this.services.getNamespaceService());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a root category in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param name String
|
||||
*/
|
||||
public CategoryNode createRootCategory(String aspect, String name)
|
||||
{
|
||||
NodeRef categoryNodeRef = services.getCategoryService().createRootCategory(storeRef, createQName(aspect), name);
|
||||
CategoryNode categoryNode = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category node from the category node reference.
|
||||
*
|
||||
* @param categoryRef category node reference
|
||||
* @return {@link CategoryNode} category node
|
||||
*/
|
||||
public CategoryNode getCategory(String categoryRef)
|
||||
{
|
||||
CategoryNode result = null;
|
||||
NodeRef categoryNodeRef = new NodeRef(categoryRef);
|
||||
if (services.getNodeService().exists(categoryNodeRef) == true &&
|
||||
services.getDictionaryService().isSubClass(ContentModel.TYPE_CATEGORY, services.getNodeService().getType(categoryNodeRef)) == true)
|
||||
{
|
||||
result = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root categories in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getRootCategories(
|
||||
storeRef, createQName(aspect)));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ordered, filtered and paged root categories in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @param filter
|
||||
* @param maxItems
|
||||
* @param skipCount (offset)
|
||||
* @return
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect, String filter, int maxItems, int skipCount)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(skipCount, maxItems);
|
||||
List<ChildAssociationRef> rootCategories = services.getCategoryService().getRootCategories(storeRef, createQName(aspect), pagingRequest, true, filter).getPage();
|
||||
Object[] cats = buildCategoryNodes(rootCategories);
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category usage count.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param maxCount int
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getCategoryUsage(String aspect, int maxCount)
|
||||
{
|
||||
List<Pair<NodeRef, Integer>> topCats = services.getCategoryService().getTopCategories(storeRef, createQName(aspect), maxCount);
|
||||
Object[] tags = new Object[topCats.size()];
|
||||
int i = 0;
|
||||
for (Pair<NodeRef, Integer> topCat : topCats)
|
||||
{
|
||||
tags[i++] = new Tag(new CategoryNode(topCat.getFirst(), this.services, getScope()), topCat.getSecond());
|
||||
}
|
||||
|
||||
return Context.getCurrentContext().newArray(getScope(), tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build category nodes.
|
||||
*
|
||||
* @param cars list of associations to category nodes
|
||||
* @return {@link Object}[] array of category nodes
|
||||
*/
|
||||
private Object[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Object[] categoryNodes = new Object[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, getScope());
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create QName from string
|
||||
*
|
||||
* @param s QName string value
|
||||
* @return {@link QName} qualified name object
|
||||
*/
|
||||
private QName createQName(String s)
|
||||
{
|
||||
QName qname;
|
||||
if (s.indexOf(QName.NAMESPACE_BEGIN) != -1)
|
||||
{
|
||||
qname = QName.createQName(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
qname = QName.createQName(s, this.services.getNamespaceService());
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag class returned from getCategoryUsage().
|
||||
*/
|
||||
public final class Tag
|
||||
{
|
||||
private CategoryNode categoryNode;
|
||||
private int frequency = 0;
|
||||
|
||||
public Tag(CategoryNode categoryNode, int frequency)
|
||||
{
|
||||
this.categoryNode = categoryNode;
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
public CategoryNode getCategory()
|
||||
{
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support class for finding categories, finding root nodes for categories and creating root categories.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public final class Classification extends BaseScopableProcessorExtension
|
||||
{
|
||||
private ServiceRegistry services;
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
/**
|
||||
* Set the default store reference
|
||||
*
|
||||
* @param storeRef the default store reference
|
||||
*/
|
||||
public void setStoreUrl(String storeRef)
|
||||
{
|
||||
this.storeRef = new StoreRef(storeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
* @param services the service registry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the category nodes in a given classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getAllCategoryNodes(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getCategories(
|
||||
storeRef, createQName(aspect), CategoryService.Depth.ANY));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the aspects that define a classification.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getAllClassificationAspects()
|
||||
{
|
||||
Collection<QName> aspects = services.getCategoryService().getClassificationAspects();
|
||||
String[] answer = new String[aspects.size()];
|
||||
int i = 0;
|
||||
for (QName qname : aspects)
|
||||
{
|
||||
answer[i++] = qname.toPrefixString(this.services.getNamespaceService());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a root category in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param name String
|
||||
*/
|
||||
public CategoryNode createRootCategory(String aspect, String name)
|
||||
{
|
||||
NodeRef categoryNodeRef = services.getCategoryService().createRootCategory(storeRef, createQName(aspect), name);
|
||||
CategoryNode categoryNode = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category node from the category node reference.
|
||||
*
|
||||
* @param categoryRef category node reference
|
||||
* @return {@link CategoryNode} category node
|
||||
*/
|
||||
public CategoryNode getCategory(String categoryRef)
|
||||
{
|
||||
CategoryNode result = null;
|
||||
NodeRef categoryNodeRef = new NodeRef(categoryRef);
|
||||
if (services.getNodeService().exists(categoryNodeRef) == true &&
|
||||
services.getDictionaryService().isSubClass(ContentModel.TYPE_CATEGORY, services.getNodeService().getType(categoryNodeRef)) == true)
|
||||
{
|
||||
result = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root categories in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getRootCategories(
|
||||
storeRef, createQName(aspect)));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ordered, filtered and paged root categories in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @param filter
|
||||
* @param maxItems
|
||||
* @param skipCount (offset)
|
||||
* @return
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect, String filter, int maxItems, int skipCount)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(skipCount, maxItems);
|
||||
List<ChildAssociationRef> rootCategories = services.getCategoryService().getRootCategories(storeRef, createQName(aspect), pagingRequest, true, filter).getPage();
|
||||
Object[] cats = buildCategoryNodes(rootCategories);
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category usage count.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param maxCount int
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getCategoryUsage(String aspect, int maxCount)
|
||||
{
|
||||
List<Pair<NodeRef, Integer>> topCats = services.getCategoryService().getTopCategories(storeRef, createQName(aspect), maxCount);
|
||||
Object[] tags = new Object[topCats.size()];
|
||||
int i = 0;
|
||||
for (Pair<NodeRef, Integer> topCat : topCats)
|
||||
{
|
||||
tags[i++] = new Tag(new CategoryNode(topCat.getFirst(), this.services, getScope()), topCat.getSecond());
|
||||
}
|
||||
|
||||
return Context.getCurrentContext().newArray(getScope(), tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build category nodes.
|
||||
*
|
||||
* @param cars list of associations to category nodes
|
||||
* @return {@link Object}[] array of category nodes
|
||||
*/
|
||||
private Object[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Object[] categoryNodes = new Object[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, getScope());
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create QName from string
|
||||
*
|
||||
* @param s QName string value
|
||||
* @return {@link QName} qualified name object
|
||||
*/
|
||||
private QName createQName(String s)
|
||||
{
|
||||
QName qname;
|
||||
if (s.indexOf(QName.NAMESPACE_BEGIN) != -1)
|
||||
{
|
||||
qname = QName.createQName(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
qname = QName.createQName(s, this.services.getNamespaceService());
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag class returned from getCategoryUsage().
|
||||
*/
|
||||
public final class Tag
|
||||
{
|
||||
private CategoryNode categoryNode;
|
||||
private int frequency = 0;
|
||||
|
||||
public Tag(CategoryNode categoryNode, int frequency)
|
||||
{
|
||||
this.categoryNode = categoryNode;
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
public CategoryNode getCategory()
|
||||
{
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,11 +514,15 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
NodeRef renditionNode = getRenditionNode(sourceNodeRef, renditionName);
|
||||
boolean createRenditionNode = renditionNode == null;
|
||||
boolean sourceHasAspectRenditioned = nodeService.hasAspect(sourceNodeRef, RenditionModel.ASPECT_RENDITIONED);
|
||||
boolean sourceChanges = !sourceHasAspectRenditioned || createRenditionNode || transformInputStream == null;
|
||||
try
|
||||
{
|
||||
ruleService.disableRuleType(RuleType.UPDATE);
|
||||
behaviourFilter.disableBehaviour(sourceNodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.disableBehaviour(sourceNodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
if (sourceChanges)
|
||||
{
|
||||
ruleService.disableRuleType(RuleType.UPDATE);
|
||||
behaviourFilter.disableBehaviour(sourceNodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.disableBehaviour(sourceNodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
}
|
||||
|
||||
// If they do not exist create the rendition association and the rendition node.
|
||||
if (createRenditionNode)
|
||||
@@ -588,9 +592,12 @@ public class RenditionService2Impl implements RenditionService2, InitializingBea
|
||||
}
|
||||
finally
|
||||
{
|
||||
behaviourFilter.enableBehaviour(sourceNodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.enableBehaviour(sourceNodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
ruleService.enableRuleType(RuleType.UPDATE);
|
||||
if (sourceChanges)
|
||||
{
|
||||
behaviourFilter.enableBehaviour(sourceNodeRef, ContentModel.ASPECT_AUDITABLE);
|
||||
behaviourFilter.enableBehaviour(sourceNodeRef, ContentModel.ASPECT_VERSIONABLE);
|
||||
ruleService.enableRuleType(RuleType.UPDATE);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, false, true));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user