mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merge branch 'master' of https://gitlab.alfresco.com/records-management/records-management into feature/RM-4396_Lombok_UseModelInsteadJsonObject
# Conflicts: # rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/fileplancomponents/FilePlanComponent.java # rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/fileplancomponents/FilePlanComponentProperties.java
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<alfresco.installer.host>nightlybuilds</alfresco.installer.host>
|
<alfresco.installer.host>releases</alfresco.installer.host>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<suiteXmlFile>testng.xml</suiteXmlFile>
|
<suiteXmlFile>testng.xml</suiteXmlFile>
|
||||||
|
@@ -33,6 +33,11 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.restassured</groupId>
|
||||||
|
<artifactId>rest-assured</artifactId>
|
||||||
|
<version>2.9.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.alfresco.tas</groupId>
|
<groupId>org.alfresco.tas</groupId>
|
||||||
<artifactId>restapi-test</artifactId>
|
<artifactId>restapi-test</artifactId>
|
||||||
|
@@ -94,6 +94,9 @@ public class FilePlanComponent
|
|||||||
@JsonProperty (value = ALLOWABLE_OPERATIONS)
|
@JsonProperty (value = ALLOWABLE_OPERATIONS)
|
||||||
private List<String> allowableOperations;
|
private List<String> allowableOperations;
|
||||||
|
|
||||||
|
@JsonProperty (required = false)
|
||||||
|
private FilePlanComponentContent content;
|
||||||
|
|
||||||
private FilePlanComponentPath path;
|
private FilePlanComponentPath path;
|
||||||
|
|
||||||
@JsonProperty (required = true)
|
@JsonProperty (required = true)
|
||||||
@@ -104,4 +107,5 @@ public class FilePlanComponent
|
|||||||
|
|
||||||
@JsonProperty (required = true)
|
@JsonProperty (required = true)
|
||||||
private FilePlanComponentUserInfo modifiedByUser;
|
private FilePlanComponentUserInfo modifiedByUser;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* 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.rm.community.model.fileplancomponents;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POJO for FilePlanComponent content field
|
||||||
|
* @author Kristijan Conkas
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
public class FilePlanComponentContent
|
||||||
|
{
|
||||||
|
@JsonProperty (required = true)
|
||||||
|
private String encoding;
|
||||||
|
|
||||||
|
@JsonProperty (required = true)
|
||||||
|
private String mimeType;
|
||||||
|
|
||||||
|
@JsonProperty (required = true)
|
||||||
|
private String mimeTypeName;
|
||||||
|
|
||||||
|
@JsonProperty (required = true)
|
||||||
|
private Integer sizeInBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the encoding
|
||||||
|
*/
|
||||||
|
public String getEncoding()
|
||||||
|
{
|
||||||
|
return this.encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param encoding the encoding to set
|
||||||
|
*/
|
||||||
|
public void setEncoding(String encoding)
|
||||||
|
{
|
||||||
|
this.encoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mimeType
|
||||||
|
*/
|
||||||
|
public String getMimeType()
|
||||||
|
{
|
||||||
|
return this.mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mimeType the mimeType to set
|
||||||
|
*/
|
||||||
|
public void setMimeType(String mimeType)
|
||||||
|
{
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mimeTypeName
|
||||||
|
*/
|
||||||
|
public String getMimeTypeName()
|
||||||
|
{
|
||||||
|
return this.mimeTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mimeTypeName the mimeTypeName to set
|
||||||
|
*/
|
||||||
|
public void setMimeTypeName(String mimeTypeName)
|
||||||
|
{
|
||||||
|
this.mimeTypeName = mimeTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the sizeInBytes
|
||||||
|
*/
|
||||||
|
public Integer getSizeInBytes()
|
||||||
|
{
|
||||||
|
return this.sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sizeInBytes the sizeInBytes to set
|
||||||
|
*/
|
||||||
|
public void setSizeInBytes(Integer sizeInBytes)
|
||||||
|
{
|
||||||
|
this.sizeInBytes = sizeInBytes;
|
||||||
|
}
|
||||||
|
}
|
@@ -45,7 +45,17 @@ public class FilePlanComponentFields
|
|||||||
public static final String PROPERTIES_DESCRIPTION = "cm:description";
|
public static final String PROPERTIES_DESCRIPTION = "cm:description";
|
||||||
public static final String PROPERTIES_SUPPLEMENTAL_MARKING_LIST = "rmc:supplementalMarkingList";
|
public static final String PROPERTIES_SUPPLEMENTAL_MARKING_LIST = "rmc:supplementalMarkingList";
|
||||||
public static final String ALLOWABLE_OPERATIONS = "allowableOperations";
|
public static final String ALLOWABLE_OPERATIONS = "allowableOperations";
|
||||||
public static final String IS_CLOSED="isClosed";
|
public static final String IS_CLOSED = "isClosed";
|
||||||
public static final String PROPERTIES_REVIEW_PERIOD="rma:reviewPeriod";
|
public static final String PROPERTIES_REVIEW_PERIOD = "rma:reviewPeriod";
|
||||||
public static final String PROPERTIES_LOCATION="rma:location";
|
public static final String PROPERTIES_LOCATION = "rma:location";
|
||||||
|
public static final String PROPERTIES_IS_CLOSED = "rma:isClosed"; // not to be confused with IS_CLOSED!
|
||||||
|
|
||||||
|
// for non-electronic records
|
||||||
|
public static final String PROPERTIES_BOX = "rma:box";
|
||||||
|
public static final String PROPERTIES_FILE = "rma:file";
|
||||||
|
public static final String PROPERTIES_NUMBER_OF_COPIES = "rma:numberOfCopies";
|
||||||
|
public static final String PROPERTIES_PHYSICAL_SIZE = "rma:physicalSize";
|
||||||
|
public static final String PROPERTIES_SHELF = "rma:shelf";
|
||||||
|
public static final String PROPERTIES_STORAGE_LOCATION = "rma:storageLocation";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -26,10 +26,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.rm.community.model.fileplancomponents;
|
package org.alfresco.rest.rm.community.model.fileplancomponents;
|
||||||
|
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_BOX;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_DESCRIPTION;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_DESCRIPTION;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_FILE;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_HOLD_REASON;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_HOLD_REASON;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_IS_CLOSED;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_LOCATION;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_LOCATION;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_NUMBER_OF_COPIES;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_PHYSICAL_SIZE;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_REVIEW_PERIOD;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_REVIEW_PERIOD;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_SHELF;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_SUPPLEMENTAL_MARKING_LIST;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_SUPPLEMENTAL_MARKING_LIST;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_TITLE;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_TITLE;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_VITAL_RECORD_INDICATOR;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentFields.PROPERTIES_VITAL_RECORD_INDICATOR;
|
||||||
@@ -83,4 +89,25 @@ public class FilePlanComponentProperties
|
|||||||
|
|
||||||
@JsonProperty(PROPERTIES_LOCATION)
|
@JsonProperty(PROPERTIES_LOCATION)
|
||||||
private String location;
|
private String location;
|
||||||
|
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_IS_CLOSED, required = false)
|
||||||
|
private Boolean isClosed;
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_BOX, required = false)
|
||||||
|
private String box;
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_FILE, required = false)
|
||||||
|
private String file;
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_SHELF, required = false)
|
||||||
|
private String shelf;
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_NUMBER_OF_COPIES, required = false)
|
||||||
|
private Integer numberOfCopies;
|
||||||
|
|
||||||
|
@JsonProperty(value = PROPERTIES_PHYSICAL_SIZE, required = false)
|
||||||
|
private Integer physicalSize;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,8 @@ public enum FilePlanComponentType
|
|||||||
TRANSFER_CONTAINER_TYPE("rma:transferContainer"),
|
TRANSFER_CONTAINER_TYPE("rma:transferContainer"),
|
||||||
UNFILED_CONTAINER_TYPE("rma:unfiledRecordContainer"),
|
UNFILED_CONTAINER_TYPE("rma:unfiledRecordContainer"),
|
||||||
FOLDER_TYPE("cm:folder"),
|
FOLDER_TYPE("cm:folder"),
|
||||||
CONTENT_TYPE("cm:content");
|
CONTENT_TYPE("cm:content"),
|
||||||
|
NON_ELECTRONIC_RECORD_TYPE("rma:nonElectronicDocument");
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.rest.rm.community.requests;
|
package org.alfresco.rest.rm.community.requests;
|
||||||
|
|
||||||
|
import static com.jayway.restassured.RestAssured.given;
|
||||||
|
|
||||||
import static org.alfresco.rest.core.RestRequest.requestWithBody;
|
import static org.alfresco.rest.core.RestRequest.requestWithBody;
|
||||||
import static org.alfresco.rest.core.RestRequest.simpleRequest;
|
import static org.alfresco.rest.core.RestRequest.simpleRequest;
|
||||||
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryObject;
|
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryObject;
|
||||||
@@ -35,10 +37,19 @@ import static org.springframework.http.HttpMethod.DELETE;
|
|||||||
import static org.springframework.http.HttpMethod.GET;
|
import static org.springframework.http.HttpMethod.GET;
|
||||||
import static org.springframework.http.HttpMethod.POST;
|
import static org.springframework.http.HttpMethod.POST;
|
||||||
import static org.springframework.http.HttpMethod.PUT;
|
import static org.springframework.http.HttpMethod.PUT;
|
||||||
|
import static org.testng.Assert.fail;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import com.google.common.io.Resources;
|
||||||
|
import com.jayway.restassured.http.ContentType;
|
||||||
|
import com.jayway.restassured.response.Response;
|
||||||
|
|
||||||
import org.alfresco.rest.core.RestAPI;
|
import org.alfresco.rest.core.RestAPI;
|
||||||
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponent;
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponent;
|
||||||
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType;
|
||||||
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentsCollection;
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentsCollection;
|
||||||
|
import org.alfresco.utility.model.UserModel;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -119,13 +130,62 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
|
|||||||
{
|
{
|
||||||
mandatoryObject("filePlanComponentProperties", filePlanComponentModel);
|
mandatoryObject("filePlanComponentProperties", filePlanComponentModel);
|
||||||
mandatoryString("parentId", parentId);
|
mandatoryString("parentId", parentId);
|
||||||
|
|
||||||
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
|
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
|
||||||
POST,
|
POST,
|
||||||
toJson(filePlanComponentModel),
|
toJson(filePlanComponentModel),
|
||||||
"fileplan-components/{fileplanComponentId}/children",
|
"fileplan-components/{fileplanComponentId}/children?{parameters}",
|
||||||
parentId
|
parentId,
|
||||||
));
|
getParameters()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create electronic record from file resource
|
||||||
|
* @param electronicRecordModel {@link FilePlanComponent} for electronic record to be created
|
||||||
|
* @param fileName the name of the resource file
|
||||||
|
* @param parentId parent container id
|
||||||
|
* @return newly created {@link FilePlanComponent}
|
||||||
|
* @throws Exception if operation failed
|
||||||
|
*/
|
||||||
|
public FilePlanComponent createElectronicRecord(FilePlanComponent electronicRecordModel, String fileName, String parentId) throws Exception
|
||||||
|
{
|
||||||
|
return createElectronicRecord(electronicRecordModel, new File(Resources.getResource(fileName).getFile()), parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create electronic record from file resource
|
||||||
|
* @param electronicRecordModel {@link FilePlanComponent} for electronic record to be created
|
||||||
|
* @param recordContent {@link File} pointing to the content of the electronic record to be created
|
||||||
|
* @param parentId parent container id
|
||||||
|
* @return newly created {@link FilePlanComponent}
|
||||||
|
* @throws Exception if operation failed
|
||||||
|
*/
|
||||||
|
public FilePlanComponent createElectronicRecord(FilePlanComponent electronicRecordModel, File recordContent, String parentId) throws Exception
|
||||||
|
{
|
||||||
|
mandatoryObject("filePlanComponentProperties", electronicRecordModel);
|
||||||
|
mandatoryString("parentId", parentId);
|
||||||
|
if (!electronicRecordModel.getNodeType().equals(FilePlanComponentType.CONTENT_TYPE.toString()))
|
||||||
|
{
|
||||||
|
fail("Only electronic records are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RestWrapper adds some headers which break multipart/form-data uploads and also assumes json POST requests.
|
||||||
|
* Upload the file using RestAssured library.
|
||||||
|
*/
|
||||||
|
UserModel currentUser = usingRestWrapper().getTestUser();
|
||||||
|
Response response = given()
|
||||||
|
.auth().basic(currentUser.getUsername(), currentUser.getPassword())
|
||||||
|
.multiPart("nodeBodyCreate", toJson(electronicRecordModel), ContentType.JSON.name())
|
||||||
|
.multiPart("filedata", recordContent, ContentType.BINARY.name())
|
||||||
|
.when()
|
||||||
|
.post("fileplan-components/{fileplanComponentId}/children?{parameters}", parentId, getParameters())
|
||||||
|
.andReturn();
|
||||||
|
usingRestWrapper().setStatusCode(Integer.toString(response.getStatusCode()));
|
||||||
|
LOG.info("electronic record created: " + response.getBody().prettyPrint());
|
||||||
|
|
||||||
|
/* return a FilePlanComponent object representing Response */
|
||||||
|
return response.jsonPath().getObject("entry", FilePlanComponent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,8 +212,9 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
|
|||||||
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
|
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
|
||||||
PUT,
|
PUT,
|
||||||
toJson(filePlanComponent),
|
toJson(filePlanComponent),
|
||||||
"fileplan-components/{fileplanComponentId}",
|
"fileplan-components/{fileplanComponentId}?{parameters}",
|
||||||
filePlanComponentId
|
filePlanComponentId,
|
||||||
|
getParameters()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,11 +30,15 @@ import static java.lang.Integer.parseInt;
|
|||||||
|
|
||||||
import static org.alfresco.rest.rm.community.base.TestData.CATEGORY_TITLE;
|
import static org.alfresco.rest.rm.community.base.TestData.CATEGORY_TITLE;
|
||||||
import static org.alfresco.rest.rm.community.base.TestData.FOLDER_TITLE;
|
import static org.alfresco.rest.rm.community.base.TestData.FOLDER_TITLE;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_CATEGORY_TYPE;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_CATEGORY_TYPE;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_FOLDER_TYPE;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_FOLDER_TYPE;
|
||||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE;
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE;
|
||||||
import static org.alfresco.rest.rm.community.model.site.RMSiteCompliance.STANDARD;
|
import static org.alfresco.rest.rm.community.model.site.RMSiteCompliance.STANDARD;
|
||||||
|
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||||
import static org.springframework.http.HttpStatus.CREATED;
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
|
|
||||||
import com.jayway.restassured.RestAssured;
|
import com.jayway.restassured.RestAssured;
|
||||||
|
|
||||||
@@ -47,11 +51,13 @@ import org.alfresco.rest.rm.community.model.site.RMSite;
|
|||||||
import org.alfresco.rest.rm.community.requests.FilePlanComponentAPI;
|
import org.alfresco.rest.rm.community.requests.FilePlanComponentAPI;
|
||||||
import org.alfresco.rest.rm.community.requests.RMSiteAPI;
|
import org.alfresco.rest.rm.community.requests.RMSiteAPI;
|
||||||
import org.alfresco.utility.data.DataUser;
|
import org.alfresco.utility.data.DataUser;
|
||||||
|
import org.alfresco.utility.model.UserModel;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all IG REST API Tests
|
* Base class for all IG REST API Tests
|
||||||
@@ -83,7 +89,7 @@ public class BaseRestTest extends RestTest
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RMSiteAPI rmSiteAPI;
|
private RMSiteAPI rmSiteAPI;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DataUser dataUser;
|
private DataUser dataUser;
|
||||||
|
|
||||||
@@ -95,6 +101,19 @@ public class BaseRestTest extends RestTest
|
|||||||
public static final String RM_TITLE = "Records Management";
|
public static final String RM_TITLE = "Records Management";
|
||||||
public static final String RM_DESCRIPTION = "Records Management Site";
|
public static final String RM_DESCRIPTION = "Records Management Site";
|
||||||
|
|
||||||
|
/** Valid root containers where electronic and non-electronic records can be created */
|
||||||
|
@DataProvider(name = "validRootContainers")
|
||||||
|
public Object[][] getValidRootContainers() throws Exception {
|
||||||
|
return new Object[][] {
|
||||||
|
// an arbitrary record folder
|
||||||
|
{ createCategoryFolderInFilePlan(dataUser.getAdminUser(), FILE_PLAN_ALIAS.toString()) },
|
||||||
|
// unfiled records root
|
||||||
|
{ getFilePlanComponentAsUser(dataUser.getAdminUser(), UNFILED_RECORDS_CONTAINER_ALIAS.toString()) },
|
||||||
|
// an arbitrary unfiled records folder
|
||||||
|
{ createUnfiledRecordsFolder(UNFILED_RECORDS_CONTAINER_ALIAS.toString(), "Unfiled Folder " + getRandomAlphanumeric()) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.alfresco.rest.RestTest#checkServerHealth()
|
* @see org.alfresco.rest.RestTest#checkServerHealth()
|
||||||
*/
|
*/
|
||||||
@@ -196,4 +215,55 @@ public class BaseRestTest extends RestTest
|
|||||||
return fpc;
|
return fpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to close folder
|
||||||
|
* @param folderToClose
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public FilePlanComponent closeFolder(String folderId) throws Exception
|
||||||
|
{
|
||||||
|
RestWrapper restWrapper = filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
// build fileplan component + properties for update request
|
||||||
|
FilePlanComponentProperties properties = new FilePlanComponentProperties();
|
||||||
|
properties.setIsClosed(true);
|
||||||
|
FilePlanComponent filePlanComponent = new FilePlanComponent();
|
||||||
|
filePlanComponent.setProperties(properties);
|
||||||
|
|
||||||
|
FilePlanComponent updatedComponent = filePlanComponentAPI.updateFilePlanComponent(filePlanComponent, folderId);
|
||||||
|
restWrapper.assertStatusCodeIs(OK);
|
||||||
|
return updatedComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to create a randomly-named <category>/<folder> structure in fileplan
|
||||||
|
* @param user user under whose privileges this structure is going to be created
|
||||||
|
* @param parentId parent container id
|
||||||
|
* @return record folder
|
||||||
|
* @throws Exception on failed creation
|
||||||
|
*/
|
||||||
|
public FilePlanComponent createCategoryFolderInFilePlan(UserModel user, String parentId) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(user);
|
||||||
|
|
||||||
|
// create root category
|
||||||
|
FilePlanComponent recordCategory = createCategory(parentId, "Category " + getRandomAlphanumeric());
|
||||||
|
|
||||||
|
// and return a folder underneath
|
||||||
|
return createFolder(recordCategory.getId(), "Folder " + getRandomAlphanumeric());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to retieve a fileplan component with user's privilege
|
||||||
|
* @param user user under whose privileges a component is to be read
|
||||||
|
* @param componentId id of the component to read
|
||||||
|
* @return {@link FilePlanComponent} for given componentId
|
||||||
|
* @throws Exception if user doesn't have sufficient privileges
|
||||||
|
*/
|
||||||
|
public FilePlanComponent getFilePlanComponentAsUser(UserModel user, String componentId) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(user);
|
||||||
|
return filePlanComponentAPI.getFilePlanComponent(componentId);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -50,7 +50,7 @@ import org.testng.annotations.DataProvider;
|
|||||||
* @since 2.6
|
* @since 2.6
|
||||||
*/
|
*/
|
||||||
public interface TestData
|
public interface TestData
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* A user with ALFRESCO_ADMINISTRATORS role.
|
* A user with ALFRESCO_ADMINISTRATORS role.
|
||||||
* <p>"GROUP_ANOTHER_ADMIN_EXISTS" The ANOTHER_ADMIN user has been created.
|
* <p>"GROUP_ANOTHER_ADMIN_EXISTS" The ANOTHER_ADMIN user has been created.
|
||||||
@@ -141,5 +141,4 @@ public interface TestData
|
|||||||
{ CONTENT_TYPE.toString()}
|
{ CONTENT_TYPE.toString()}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* 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.rm.community.fileplancomponents;
|
||||||
|
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.HOLDS_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.TRANSFERS_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.CONTENT_TYPE;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_FOLDER_TYPE;
|
||||||
|
import static org.alfresco.rest.rm.community.util.PojoUtility.toJson;
|
||||||
|
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
|
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.alfresco.rest.rm.community.base.BaseRestTest;
|
||||||
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponent;
|
||||||
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentProperties;
|
||||||
|
import org.alfresco.rest.rm.community.requests.FilePlanComponentAPI;
|
||||||
|
import org.alfresco.utility.data.DataUser;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create/File electronic records tests
|
||||||
|
* <br>
|
||||||
|
* These tests only test the creation and filing of electronic records, update at
|
||||||
|
* present isn't implemented in the API under test.
|
||||||
|
* <p>
|
||||||
|
* @author Kristijan Conkas
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
public class ElectronicRecordTests extends BaseRestTest
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private FilePlanComponentAPI filePlanComponentAPI;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DataUser dataUser;
|
||||||
|
|
||||||
|
/** image resource file to be used for records body */
|
||||||
|
private static final String IMAGE_FILE = "money.JPG";
|
||||||
|
|
||||||
|
/** Valid root containers where electronic records can be created */
|
||||||
|
@DataProvider(name = "invalidParentContainers")
|
||||||
|
public Object[][] invalidContainers() throws Exception {
|
||||||
|
return new Object[][] {
|
||||||
|
// record category
|
||||||
|
{ getFilePlanComponentAsUser(dataUser.getAdminUser(),
|
||||||
|
createCategoryFolderInFilePlan(dataUser.getAdminUser(), FILE_PLAN_ALIAS.toString()).getParentId()) },
|
||||||
|
// file plan root
|
||||||
|
{ getFilePlanComponentAsUser(dataUser.getAdminUser(), FILE_PLAN_ALIAS.toString()) },
|
||||||
|
// transfers
|
||||||
|
{ getFilePlanComponentAsUser(dataUser.getAdminUser(), TRANSFERS_ALIAS.toString()) },
|
||||||
|
// holds
|
||||||
|
{ getFilePlanComponentAsUser(dataUser.getAdminUser(), HOLDS_ALIAS.toString()) },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is NOT a record folder or an unfiled record folder
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @param container
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "invalidParentContainers",
|
||||||
|
description = "Electronic records can't be created in invalid parent containers"
|
||||||
|
)
|
||||||
|
public void cantCreateElectronicRecordsInInvalidContainers(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
FilePlanComponent record = new FilePlanComponent("Record " + getRandomAlphanumeric(), CONTENT_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties());
|
||||||
|
filePlanComponentAPI.createElectronicRecord(record, IMAGE_FILE, container.getId());
|
||||||
|
|
||||||
|
// verify the create request status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is closed
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test(description = "Electronic record can't be created in closed record folder")
|
||||||
|
public void cantCreateElectronicRecordInClosedFolder() throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
FilePlanComponent recordFolder = createCategoryFolderInFilePlan(dataUser.getAdminUser(), FILE_PLAN_ALIAS.toString());
|
||||||
|
|
||||||
|
// the folder should be open
|
||||||
|
assertFalse(recordFolder.getProperties().getIsClosed());
|
||||||
|
|
||||||
|
// close the folder
|
||||||
|
closeFolder(recordFolder.getId());
|
||||||
|
|
||||||
|
// try to create it, this should fail
|
||||||
|
FilePlanComponent record = new FilePlanComponent("Record " + getRandomAlphanumeric(), CONTENT_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties());
|
||||||
|
filePlanComponentAPI.createElectronicRecord(record, IMAGE_FILE, recordFolder.getId());
|
||||||
|
|
||||||
|
// verify the status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is open
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* And I do not provide all the required mandatory property values
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* and
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is an unfiled record folder or the root unfiled record container
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* And I do not provide all the required mandatory property values
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @param container
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "validRootContainers",
|
||||||
|
description = "Electronic record can only be created if all mandatory properties are given"
|
||||||
|
)
|
||||||
|
public void canCreateElectronicRecordOnlyWithMandatoryProperties(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
logger.info("Root container:\n" + toJson(container));
|
||||||
|
if (container.getNodeType().equals(RECORD_FOLDER_TYPE.toString()))
|
||||||
|
{
|
||||||
|
// only record folders can be open or closed
|
||||||
|
assertFalse(container.getProperties().getIsClosed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// component without name
|
||||||
|
FilePlanComponent record = new FilePlanComponent();
|
||||||
|
record.setNodeType(CONTENT_TYPE.toString());
|
||||||
|
record.setProperties(new FilePlanComponentProperties());
|
||||||
|
|
||||||
|
// try to create it
|
||||||
|
filePlanComponentAPI.createFilePlanComponent(record, container.getId());
|
||||||
|
|
||||||
|
// verify the status code is BAD_REQUEST
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is open
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* Then the electronic record is created
|
||||||
|
* And the details of the new record are returned
|
||||||
|
* </pre>
|
||||||
|
* and
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is an unfiled record folder or the root unfiled record container
|
||||||
|
* When I try to create an electronic record within the parent container
|
||||||
|
* Then the electronic record is created
|
||||||
|
* And the details of the new record are returned
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "validRootContainers",
|
||||||
|
description = "Electronic records can be created in unfiled record folder or unfiled record root"
|
||||||
|
)
|
||||||
|
public void canCreateElectronicRecordsInValidContainers(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
FilePlanComponent record = new FilePlanComponent("Record " + getRandomAlphanumeric(), CONTENT_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties());
|
||||||
|
String newRecordId = filePlanComponentAPI.createElectronicRecord(record, IMAGE_FILE, container.getId()).getId();
|
||||||
|
|
||||||
|
// verify the create request status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(CREATED);
|
||||||
|
|
||||||
|
// get newly created electonic record and verify its properties
|
||||||
|
FilePlanComponent electronicRecord = filePlanComponentAPI.getFilePlanComponent(newRecordId);
|
||||||
|
// record will have record identifier inserted in its name but will for sure start with file name
|
||||||
|
// and end with its extension
|
||||||
|
assertTrue(electronicRecord.getName().startsWith(IMAGE_FILE.substring(0, IMAGE_FILE.indexOf("."))));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* 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.rm.community.fileplancomponents;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.HOLDS_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.TRANSFERS_ALIAS;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.NON_ELECTRONIC_RECORD_TYPE;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_CATEGORY_TYPE;
|
||||||
|
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.RECORD_FOLDER_TYPE;
|
||||||
|
import static org.alfresco.rest.rm.community.util.PojoUtility.toJson;
|
||||||
|
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
import static org.springframework.http.HttpStatus.CREATED;
|
||||||
|
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||||
|
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.alfresco.rest.rm.community.base.BaseRestTest;
|
||||||
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponent;
|
||||||
|
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentProperties;
|
||||||
|
import org.alfresco.rest.rm.community.requests.FilePlanComponentAPI;
|
||||||
|
import org.alfresco.rest.rm.community.requests.RMSiteAPI;
|
||||||
|
import org.alfresco.utility.constants.UserRole;
|
||||||
|
import org.alfresco.utility.data.DataUser;
|
||||||
|
import org.alfresco.utility.model.SiteModel;
|
||||||
|
import org.alfresco.utility.model.UserModel;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create/File Non-Electronic Record into Unfiled Record Container/Record Folder ReST API tests
|
||||||
|
*
|
||||||
|
* @author Kristijan Conkas
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
public class NonElectronicRecordTests extends BaseRestTest
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private FilePlanComponentAPI filePlanComponentAPI;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DataUser dataUser;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RMSiteAPI rmSiteAPI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is NOT a record folder or an unfiled record folder
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception if prerequisites can't be created
|
||||||
|
*/
|
||||||
|
@Test(description = "Non-electronic record can't be created as a child of invalid parent Id")
|
||||||
|
public void cantCreateForInvalidParentIds() throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
// non-electronic record object to be used for create tests
|
||||||
|
FilePlanComponent nonElectronicRecord = new FilePlanComponent(
|
||||||
|
"Record " + getRandomAlphanumeric(),
|
||||||
|
NON_ELECTRONIC_RECORD_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties());
|
||||||
|
|
||||||
|
// create record category, non-electronic records can't be its children
|
||||||
|
FilePlanComponent recordCategory = filePlanComponentAPI.createFilePlanComponent(
|
||||||
|
new FilePlanComponent("Category " + getRandomAlphanumeric(),
|
||||||
|
RECORD_CATEGORY_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties()),
|
||||||
|
FILE_PLAN_ALIAS.toString());
|
||||||
|
|
||||||
|
// iterate through all invalid parent containers and try to create/file an electronic record
|
||||||
|
asList(FILE_PLAN_ALIAS.toString(), TRANSFERS_ALIAS.toString(), HOLDS_ALIAS.toString(), recordCategory.getId())
|
||||||
|
.stream()
|
||||||
|
.forEach(id ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.createFilePlanComponent(nonElectronicRecord, id);
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(UNPROCESSABLE_ENTITY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is open
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* Then the non-electronic record is created
|
||||||
|
* And the details of the new record are returned
|
||||||
|
* <pre>
|
||||||
|
* and
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is an unfiled record folder or the root unfiled record container
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* Then the non-electronic record is created
|
||||||
|
* And the details of the new record are returned
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception if record can't be created
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "validRootContainers",
|
||||||
|
description = "Non-electronic records can be created in valid containers"
|
||||||
|
)
|
||||||
|
public void canCreateInValidContainers(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
logger.info("Root container:\n" + toJson(container));
|
||||||
|
if (container.getNodeType().equals(RECORD_FOLDER_TYPE.toString()))
|
||||||
|
{
|
||||||
|
// only record folders can be open or closed
|
||||||
|
assertFalse(container.getProperties().getIsClosed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// use these properties for non-electronic record to be created
|
||||||
|
String title = "Title " + getRandomAlphanumeric();
|
||||||
|
String description = "Description " + getRandomAlphanumeric();
|
||||||
|
String box = "Box "+ getRandomAlphanumeric();
|
||||||
|
String file = "File " + getRandomAlphanumeric();
|
||||||
|
String shelf = "Shelf " + getRandomAlphanumeric();
|
||||||
|
String location = "Location " + getRandomAlphanumeric();
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
Integer copies = random.nextInt(Integer.MAX_VALUE);
|
||||||
|
Integer size = random.nextInt(Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
// set values of all available properties
|
||||||
|
FilePlanComponentProperties properties = new FilePlanComponentProperties(title, description);
|
||||||
|
properties.setBox(box);
|
||||||
|
properties.setFile(file);
|
||||||
|
properties.setShelf(shelf);
|
||||||
|
properties.setLocation(location);
|
||||||
|
properties.setNumberOfCopies(copies);
|
||||||
|
properties.setPhysicalSize(size);
|
||||||
|
|
||||||
|
// create non-electronic record
|
||||||
|
String nonElectronicId = filePlanComponentAPI.createFilePlanComponent(
|
||||||
|
new FilePlanComponent("Record " + getRandomAlphanumeric(),
|
||||||
|
NON_ELECTRONIC_RECORD_TYPE.toString(),
|
||||||
|
properties),
|
||||||
|
container.getId()).getId();
|
||||||
|
|
||||||
|
// verify the create request status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(CREATED);
|
||||||
|
|
||||||
|
// get newly created non-electonic record and verify its properties
|
||||||
|
FilePlanComponent nonElectronicRecord = filePlanComponentAPI.getFilePlanComponent(nonElectronicId);
|
||||||
|
|
||||||
|
assertEquals(title, nonElectronicRecord.getProperties().getTitle());
|
||||||
|
assertEquals(description, nonElectronicRecord.getProperties().getDescription());
|
||||||
|
assertEquals(box, nonElectronicRecord.getProperties().getBox());
|
||||||
|
assertEquals(file, nonElectronicRecord.getProperties().getFile());
|
||||||
|
assertEquals(shelf, nonElectronicRecord.getProperties().getShelf());
|
||||||
|
assertEquals(location, nonElectronicRecord.getProperties().getLocation());
|
||||||
|
assertEquals(copies, nonElectronicRecord.getProperties().getNumberOfCopies());
|
||||||
|
assertEquals(size, nonElectronicRecord.getProperties().getPhysicalSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is closed
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception if prerequisites can't be created
|
||||||
|
*/
|
||||||
|
@Test(description = "Non-electronic record can't be created in closed record folder")
|
||||||
|
public void cantCreateInClosedFolder() throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
FilePlanComponent recordFolder = createCategoryFolderInFilePlan(dataUser.getAdminUser(), FILE_PLAN_ALIAS.toString());
|
||||||
|
|
||||||
|
// the folder should be open
|
||||||
|
assertFalse(recordFolder.getProperties().getIsClosed());
|
||||||
|
|
||||||
|
// close the folder
|
||||||
|
closeFolder(recordFolder.getId());
|
||||||
|
|
||||||
|
// try to create it, this should fail and throw an exception
|
||||||
|
|
||||||
|
filePlanComponentAPI.createFilePlanComponent(
|
||||||
|
new FilePlanComponent("Record " + getRandomAlphanumeric(),
|
||||||
|
NON_ELECTRONIC_RECORD_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties()),
|
||||||
|
recordFolder.getId()).getId();
|
||||||
|
|
||||||
|
// verify the status code
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(UNPROCESSABLE_ENTITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is a record folder
|
||||||
|
* And the record folder is open
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* And I do not provide all the required mandatory property values
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* and
|
||||||
|
* <pre>
|
||||||
|
* Given a parent container that is an unfiled record folder or the root unfiled record container
|
||||||
|
* When I try to create a non-electronic record within the parent container
|
||||||
|
* And I do not provide all the required mandatory property values
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception if prerequisites can't be created
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "validRootContainers",
|
||||||
|
description = "Non-electronic record can only be created if all mandatory properties are given"
|
||||||
|
)
|
||||||
|
public void allMandatoryPropertiesRequired(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
|
logger.info("Root container:\n" + toJson(container));
|
||||||
|
if (container.getNodeType().equals(RECORD_FOLDER_TYPE.toString()))
|
||||||
|
{
|
||||||
|
// only record folders can be open or closed
|
||||||
|
assertFalse(container.getProperties().getIsClosed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// component without name and title
|
||||||
|
FilePlanComponent noNameOrTitle = getDummyNonElectronicRecord();
|
||||||
|
|
||||||
|
// component with title only
|
||||||
|
FilePlanComponent titleOnly = getDummyNonElectronicRecord();
|
||||||
|
FilePlanComponentProperties properties = new FilePlanComponentProperties();
|
||||||
|
properties.setTitle("Title " + getRandomAlphanumeric());
|
||||||
|
titleOnly.setProperties(properties);
|
||||||
|
|
||||||
|
// try to create invalid components
|
||||||
|
asList(noNameOrTitle, titleOnly).stream().forEach(c ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.info("Creating non-electronic record with body:\n" + toJson(c));
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should fail and throw an exception
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.createFilePlanComponent(c, container.getId());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the status code is BAD_REQUEST
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(BAD_REQUEST);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Given that I am a user without RM privileges
|
||||||
|
* When I try to create a non-electronic record
|
||||||
|
* Then nothing happens
|
||||||
|
* And an error is reported
|
||||||
|
* </pre>
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
(
|
||||||
|
dataProvider = "validRootContainers",
|
||||||
|
description = "Non-electronic record can't be created if user doesn't have RM privileges"
|
||||||
|
)
|
||||||
|
public void cantCreateIfNoRmPrivileges(FilePlanComponent container) throws Exception
|
||||||
|
{
|
||||||
|
String username = "zzzuser";
|
||||||
|
UserModel user = createUserWithRole(username, UserRole.SiteManager);
|
||||||
|
|
||||||
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(user);
|
||||||
|
|
||||||
|
// try to create a fileplan component
|
||||||
|
FilePlanComponent record = new FilePlanComponent("Record Name", NON_ELECTRONIC_RECORD_TYPE.toString(),
|
||||||
|
new FilePlanComponentProperties("Name", "Title"));
|
||||||
|
|
||||||
|
// this should fail and throw an exception
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filePlanComponentAPI.createFilePlanComponent(record, container.getId());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// user who isn't an RM site member can't access the container path
|
||||||
|
filePlanComponentAPI.usingRestWrapper().assertStatusCodeIs(FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to return an empty FilePlanComponent for non-electronic record
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private FilePlanComponent getDummyNonElectronicRecord()
|
||||||
|
{
|
||||||
|
FilePlanComponent component = new FilePlanComponent();
|
||||||
|
component.setNodeType(NON_ELECTRONIC_RECORD_TYPE.toString());
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create user with given role and add it to RM site
|
||||||
|
* <br>
|
||||||
|
* Checks whether the user exists in RM site and creates it if required, with password identical
|
||||||
|
* to username. Note the role is a Core API role, not an RM role.
|
||||||
|
* <br>
|
||||||
|
* For already existing users, no site membership or role verification is performed.
|
||||||
|
* <p>
|
||||||
|
* @param userName username to add
|
||||||
|
* @param userRole user's role
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private UserModel createUserWithRole(String userName, UserRole userRole) throws Exception
|
||||||
|
{
|
||||||
|
rmSiteAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
String siteId = rmSiteAPI.getSite().getId();
|
||||||
|
|
||||||
|
// check if user exists
|
||||||
|
UserModel user = new UserModel();
|
||||||
|
user.setUsername(userName);
|
||||||
|
user.setPassword(userName);
|
||||||
|
|
||||||
|
if (!dataUser.isUserInRepo(userName))
|
||||||
|
{
|
||||||
|
// user doesn't exist, create it
|
||||||
|
user = dataUser.createUser(userName, userName);
|
||||||
|
user.setUserRole(userRole);
|
||||||
|
|
||||||
|
dataUser.addUserToSite(user, new SiteModel(siteId), userRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
@@ -100,7 +100,7 @@ public class UnfiledRecordsFolderTests extends BaseRestTest
|
|||||||
public void createRootUnfiledRecordsFolder() throws Exception
|
public void createRootUnfiledRecordsFolder() throws Exception
|
||||||
{
|
{
|
||||||
// Authenticate with admin user
|
// Authenticate with admin user
|
||||||
RestWrapper restWrapper = filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
String folderName = "Folder " + getRandomAlphanumeric();
|
String folderName = "Folder " + getRandomAlphanumeric();
|
||||||
String folderTitle = folderName + " Title";
|
String folderTitle = folderName + " Title";
|
||||||
@@ -148,7 +148,7 @@ public class UnfiledRecordsFolderTests extends BaseRestTest
|
|||||||
)
|
)
|
||||||
public void onlyRecordFoldersCanBeCreatedAtUnfiledRecordsRoot(FilePlanComponentType componentType)
|
public void onlyRecordFoldersCanBeCreatedAtUnfiledRecordsRoot(FilePlanComponentType componentType)
|
||||||
{
|
{
|
||||||
RestWrapper restWrapper = filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
filePlanComponentAPI.usingRestWrapper().authenticateUser(dataUser.getAdminUser());
|
||||||
|
|
||||||
String folderName = "Folder " + getRandomAlphanumeric();
|
String folderName = "Folder " + getRandomAlphanumeric();
|
||||||
String folderTitle = folderName + " Title";
|
String folderTitle = folderName + " Title";
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 528 KiB |
@@ -292,10 +292,16 @@
|
|||||||
<type>d:int</type>
|
<type>d:int</type>
|
||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
<index enabled="true">
|
<index enabled="true">
|
||||||
<atomic>true</atomic>
|
<atomic>true</atomic>
|
||||||
<stored>false</stored>
|
<stored>false</stored>
|
||||||
<tokenised>false</tokenised>
|
<tokenised>false</tokenised>
|
||||||
</index>
|
</index>
|
||||||
|
<constraints>
|
||||||
|
<constraint type="MINMAX">
|
||||||
|
<parameter name="minValue"><value>0</value></parameter>
|
||||||
|
<parameter name="maxValue"><value>2147483647</value></parameter> <!--MAX_INT -->
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<property name="rma:numberOfCopies">
|
<property name="rma:numberOfCopies">
|
||||||
@@ -304,10 +310,16 @@
|
|||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
<default>1</default>
|
<default>1</default>
|
||||||
<index enabled="true">
|
<index enabled="true">
|
||||||
<atomic>true</atomic>
|
<atomic>true</atomic>
|
||||||
<stored>false</stored>
|
<stored>false</stored>
|
||||||
<tokenised>false</tokenised>
|
<tokenised>false</tokenised>
|
||||||
</index>
|
</index>
|
||||||
|
<constraints>
|
||||||
|
<constraint type="MINMAX">
|
||||||
|
<parameter name="minValue"><value>0</value></parameter>
|
||||||
|
<parameter name="maxValue"><value>2147483647</value></parameter> <!--MAX_INT -->
|
||||||
|
</constraint>
|
||||||
|
</constraints>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<property name="rma:storageLocation">
|
<property name="rma:storageLocation">
|
||||||
|
@@ -49,6 +49,10 @@
|
|||||||
<property name="nodes" ref="rm.Nodes" />
|
<property name="nodes" ref="rm.Nodes" />
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean class="org.alfresco.rm.rest.api.nodes.RecordsEntityResource">
|
||||||
|
<property name="nodes" ref="rm.Nodes" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean class="org.alfresco.rm.rest.api.nodes.FileplanComponentChildrenRelation">
|
<bean class="org.alfresco.rm.rest.api.nodes.FileplanComponentChildrenRelation">
|
||||||
<property name="nodes" ref="rm.Nodes" />
|
<property name="nodes" ref="rm.Nodes" />
|
||||||
</bean>
|
</bean>
|
||||||
|
@@ -268,6 +268,12 @@
|
|||||||
<groupId>${alfresco.groupId}</groupId>
|
<groupId>${alfresco.groupId}</groupId>
|
||||||
<artifactId>alfresco-remote-api</artifactId>
|
<artifactId>alfresco-remote-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.takari.junit</groupId>
|
<groupId>io.takari.junit</groupId>
|
||||||
<artifactId>takari-cpsuite</artifactId>
|
<artifactId>takari-cpsuite</artifactId>
|
||||||
|
@@ -31,6 +31,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.rest.api.model.Node;
|
import org.alfresco.rest.api.model.Node;
|
||||||
|
import org.alfresco.rest.framework.WebApiDescription;
|
||||||
|
import org.alfresco.rest.framework.WebApiParam;
|
||||||
|
import org.alfresco.rest.framework.core.exceptions.ApiException;
|
||||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||||
import org.alfresco.rest.framework.resource.actions.interfaces.MultiPartRelationshipResourceAction;
|
import org.alfresco.rest.framework.resource.actions.interfaces.MultiPartRelationshipResourceAction;
|
||||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||||
@@ -59,12 +62,14 @@ public class FileplanComponentChildrenRelation implements RelationshipResourceAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@WebApiDescription(title = "Return a paged list of fileplan components for the container identified by parentFolderNodeId")
|
||||||
public CollectionWithPagingInfo<Node> readAll(String parentFolderNodeId, Parameters parameters)
|
public CollectionWithPagingInfo<Node> readAll(String parentFolderNodeId, Parameters parameters)
|
||||||
{
|
{
|
||||||
return nodes.listChildren(parentFolderNodeId, parameters);
|
return nodes.listChildren(parentFolderNodeId, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@WebApiDescription(title="Create one (or more) nodes as children of container identified by parentFolderNodeId")
|
||||||
public List<Node> create(String parentFolderNodeId, List<Node> nodeInfos, Parameters parameters)
|
public List<Node> create(String parentFolderNodeId, List<Node> nodeInfos, Parameters parameters)
|
||||||
{
|
{
|
||||||
List<Node> result = new ArrayList<>(nodeInfos.size());
|
List<Node> result = new ArrayList<>(nodeInfos.size());
|
||||||
@@ -78,8 +83,29 @@ public class FileplanComponentChildrenRelation implements RelationshipResourceAc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@WebApiDescription(title = "Upload file content and meta-data into the repository.")
|
||||||
|
@WebApiParam(name = "formData", title = "A single form data", description = "A single form data which holds FormFields.")
|
||||||
public Node create(String parentFolderNodeId, FormData formData, Parameters parameters, WithResponse withResponse)
|
public Node create(String parentFolderNodeId, FormData formData, Parameters parameters, WithResponse withResponse)
|
||||||
{
|
{
|
||||||
return nodes.upload(parentFolderNodeId, formData, parameters);
|
try
|
||||||
|
{
|
||||||
|
return nodes.upload(parentFolderNodeId, formData, parameters);
|
||||||
|
}
|
||||||
|
catch (ApiException apiException)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The upload method encapsulates most exceptions that can occur on node creation in an ApiException.
|
||||||
|
* To allow the API framework to correctly map the exception to the API error code we throw the original exception.
|
||||||
|
*/
|
||||||
|
Throwable originalException = apiException.getCause();
|
||||||
|
if (originalException != null && originalException instanceof RuntimeException)
|
||||||
|
{
|
||||||
|
throw (RuntimeException) originalException;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw apiException;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Records Management Module
|
||||||
|
* %%
|
||||||
|
* 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.rm.rest.api.nodes;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.alfresco.rest.api.model.Node;
|
||||||
|
import org.alfresco.rest.framework.BinaryProperties;
|
||||||
|
import org.alfresco.rest.framework.WebApiDescription;
|
||||||
|
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||||
|
import org.alfresco.rest.framework.resource.EntityResource;
|
||||||
|
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BasicContentInfo;
|
||||||
|
import org.alfresco.rest.framework.resource.content.BinaryResource;
|
||||||
|
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||||
|
import org.alfresco.rm.rest.api.RMNodes;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of an Entity Resource for a record
|
||||||
|
*
|
||||||
|
* @author Ana Bozianu
|
||||||
|
* @since 2.6
|
||||||
|
*/
|
||||||
|
@EntityResource(name="records", title = "Records")
|
||||||
|
public class RecordsEntityResource implements BinaryResourceAction.Update<Node>,
|
||||||
|
BinaryResourceAction.Read,
|
||||||
|
InitializingBean
|
||||||
|
{
|
||||||
|
|
||||||
|
private RMNodes nodes;
|
||||||
|
|
||||||
|
public void setNodes(RMNodes nodes)
|
||||||
|
{
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("nodes", this.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download content
|
||||||
|
*
|
||||||
|
* @param recordId the id of the record to get the content from
|
||||||
|
* @param parameters {@link Parameters}
|
||||||
|
* @return binary content resource
|
||||||
|
* @throws EntityNotFoundException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@WebApiDescription(title = "Download content", description = "Download content")
|
||||||
|
@BinaryProperties({"content"})
|
||||||
|
public BinaryResource readProperty(String recordId, Parameters parameters) throws EntityNotFoundException
|
||||||
|
{
|
||||||
|
return nodes.getContent(recordId, parameters, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload new version of content
|
||||||
|
*
|
||||||
|
* This allow binary content update of an existing record.
|
||||||
|
*
|
||||||
|
* Note: alternatively, can upload via POST (multipart/form-data) with existing file name and form "overwrite=true".
|
||||||
|
*
|
||||||
|
* @param recordId the id of the record to set the content for
|
||||||
|
* @param contentInfo Basic information about the content stream
|
||||||
|
* @param stream an inputstream representing the new content of the node
|
||||||
|
* @param parameters {@link Parameters}
|
||||||
|
* @return information about the record that has been updated
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@WebApiDescription(title = "Upload content", description = "Upload content")
|
||||||
|
@BinaryProperties({"content"})
|
||||||
|
public Node updateProperty(String recordId, BasicContentInfo contentInfo, InputStream stream, Parameters parameters)
|
||||||
|
{
|
||||||
|
return nodes.updateContent(recordId, contentInfo, stream, parameters);
|
||||||
|
}
|
||||||
|
}
|
@@ -19,6 +19,8 @@ tags:
|
|||||||
description: Retrieve and manage fileplan components
|
description: Retrieve and manage fileplan components
|
||||||
- name: ig-sites
|
- name: ig-sites
|
||||||
description: Retrieve and manage the RM site
|
description: Retrieve and manage the RM site
|
||||||
|
- name: records
|
||||||
|
description: Perform record specific operations
|
||||||
paths:
|
paths:
|
||||||
'/fileplan-components/{fileplanComponentId}':
|
'/fileplan-components/{fileplanComponentId}':
|
||||||
get:
|
get:
|
||||||
@@ -47,6 +49,8 @@ paths:
|
|||||||
Invalid parameter: **fileplanComponentId** is not a valid format
|
Invalid parameter: **fileplanComponentId** is not a valid format
|
||||||
'401':
|
'401':
|
||||||
description: If authentication fails
|
description: If authentication fails
|
||||||
|
'403':
|
||||||
|
description: If current user does not have permission to read **fileplanComponentId**
|
||||||
'404':
|
'404':
|
||||||
description: If **fileplanComponentId** does not exist
|
description: If **fileplanComponentId** does not exist
|
||||||
default:
|
default:
|
||||||
@@ -180,6 +184,8 @@ paths:
|
|||||||
$ref: '#/definitions/IGNodeAssociationPaging'
|
$ref: '#/definitions/IGNodeAssociationPaging'
|
||||||
'401':
|
'401':
|
||||||
description: If authentication fails
|
description: If authentication fails
|
||||||
|
'403':
|
||||||
|
description: If current user does not have permission to read **fileplanComponentId**
|
||||||
'404':
|
'404':
|
||||||
description: If **fileplanComponentId** does not exist
|
description: If **fileplanComponentId** does not exist
|
||||||
default:
|
default:
|
||||||
@@ -194,9 +200,10 @@ paths:
|
|||||||
Create a fileplan component as a primary child of node **fileplanComponentId**.
|
Create a fileplan component as a primary child of node **fileplanComponentId**.
|
||||||
|
|
||||||
This API method supports file upload using multipart/form-data.
|
This API method supports file upload using multipart/form-data.
|
||||||
|
Electronic records are the only nodes that have content.
|
||||||
|
|
||||||
Use the **filedata** field to represent the content to upload.
|
Use the **filedata** field to represent the content to upload.
|
||||||
You can use a **name** field to give an alternative name for the new file.
|
You can use a **name** field to give an alternative name for the new electronic record.
|
||||||
|
|
||||||
For multipart/form-data upload you can use the **renditions** field to create renditions (e.g. doclib) asynchronously upon upload.
|
For multipart/form-data upload you can use the **renditions** field to create renditions (e.g. doclib) asynchronously upon upload.
|
||||||
Note that currently only one rendition can be requested. Also, as requesting rendition is a background process,
|
Note that currently only one rendition can be requested. Also, as requesting rendition is a background process,
|
||||||
@@ -280,6 +287,14 @@ paths:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can create an empty electronic record and use the record endpoint to create content:
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"name":"My Electronic Record",
|
||||||
|
"nodeType":"cm:content"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
You can create a fileplan component inside a container hierarchy:
|
You can create a fileplan component inside a container hierarchy:
|
||||||
```JSON
|
```JSON
|
||||||
{
|
{
|
||||||
@@ -547,6 +562,123 @@ paths:
|
|||||||
description: Unexpected error
|
description: Unexpected error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Error'
|
$ref: '#/definitions/Error'
|
||||||
|
'/records/{recordId}/content':
|
||||||
|
get:
|
||||||
|
x-alfresco-since: "5.2"
|
||||||
|
tags:
|
||||||
|
- records
|
||||||
|
summary: Get record content
|
||||||
|
description: |
|
||||||
|
|
||||||
|
Gets the content of the record with identifier **recordId**.
|
||||||
|
operationId: getRecordContent
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/recordIdParam'
|
||||||
|
- $ref: '#/parameters/attachmentParam'
|
||||||
|
- $ref: '#/parameters/ifModifiedSinceHeader'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful response
|
||||||
|
'304':
|
||||||
|
description: Content has not been modified since the date provided in the If-Modified-Since header
|
||||||
|
'400':
|
||||||
|
description: |
|
||||||
|
Invalid parameter: **nodeId** is not a valid format, or is not a file
|
||||||
|
'401':
|
||||||
|
description: Authentication failed
|
||||||
|
'404':
|
||||||
|
description: |
|
||||||
|
**nodeId** does not exist
|
||||||
|
default:
|
||||||
|
description: Unexpected error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Error'
|
||||||
|
put:
|
||||||
|
x-alfresco-since: "5.2"
|
||||||
|
tags:
|
||||||
|
- records
|
||||||
|
summary: Update record content
|
||||||
|
description: |
|
||||||
|
Updates the content of the record with identifier **recordId**.
|
||||||
|
|
||||||
|
The request body for this endpoint can be any text or binary stream.
|
||||||
|
|
||||||
|
The **majorVersion** and **comment** parameters can be used to control versioning behaviour. If the content is versionable,
|
||||||
|
a new minor version is created by default.
|
||||||
|
|
||||||
|
Optionally a new **name** parameter can also be specified that must be unique within the parent folder. If specified and valid then this
|
||||||
|
will rename the node. If invalid then an error is returned and the content is not updated.
|
||||||
|
|
||||||
|
**Note:** This API method accepts any content type, but for testing with this tool text based content can be provided.
|
||||||
|
This is because the OpenAPI Specification does not allow a wildcard to be provided or the ability for
|
||||||
|
tooling to accept an arbitrary file.
|
||||||
|
operationId: updateRecordContent
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/parameters/recordIdParam'
|
||||||
|
- name: majorVersion
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
If **true**, create a major version.
|
||||||
|
Setting this parameter also enables versioning of this node, if it is not already versioned.
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
- name: comment
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Add a version comment which will appear in version history.
|
||||||
|
Setting this parameter also enables versioning of this node, if it is not already versioned.
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
- name: name
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
Optional new name. This should include the file extension.
|
||||||
|
The name must not contain spaces or the following special characters: * " < > \ / ? : and |.
|
||||||
|
The character `.` must not be used at the end of the name.
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
pattern: "^(?!(.*[\\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$))"
|
||||||
|
- $ref: '#/parameters/IGNodeEntryIncludeParam'
|
||||||
|
- $ref: '#/parameters/fieldsParam'
|
||||||
|
- in: body
|
||||||
|
name: contentBodyUpdate
|
||||||
|
description: The binary content
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
consumes:
|
||||||
|
- application/octet-stream
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful response
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/IGNodeEntry'
|
||||||
|
'400':
|
||||||
|
description: |
|
||||||
|
Invalid parameter: **recordId** is not a valid format, or is not a file
|
||||||
|
'401':
|
||||||
|
description: Authentication failed
|
||||||
|
'403':
|
||||||
|
description: Current user does not have permission to update **recordId**
|
||||||
|
'404':
|
||||||
|
description: |
|
||||||
|
**recordId** does not exist
|
||||||
|
'409':
|
||||||
|
description: Optional new name clashes with an existing node in the current parent folder
|
||||||
|
'413':
|
||||||
|
description: Content exceeds individual file size limit (configured for network/system)
|
||||||
|
'422':
|
||||||
|
description: Model integrity exception including a file name containing invalid characters
|
||||||
|
'507':
|
||||||
|
description: Content exceeds overall storage quota limit configured for the network/system
|
||||||
|
default:
|
||||||
|
description: Unexpected error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/Error'
|
||||||
parameters:
|
parameters:
|
||||||
fileplanComponentIdWithAliasParam:
|
fileplanComponentIdWithAliasParam:
|
||||||
name: fileplanComponentId
|
name: fileplanComponentId
|
||||||
@@ -609,13 +741,18 @@ parameters:
|
|||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
collectionFormat: csv
|
collectionFormat: csv
|
||||||
## Core definition
|
|
||||||
fileplanComponentIdParam:
|
fileplanComponentIdParam:
|
||||||
name: fileplanComponentId
|
name: fileplanComponentId
|
||||||
in: path
|
in: path
|
||||||
description: The identifier of a fileplan compoment.
|
description: The identifier of a fileplan compoment.
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
recordIdParam:
|
||||||
|
name: recordId
|
||||||
|
in: path
|
||||||
|
description: The identifier of a record.
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
## Core definition
|
## Core definition
|
||||||
fieldsParam:
|
fieldsParam:
|
||||||
name: fields
|
name: fields
|
||||||
@@ -670,6 +807,33 @@ parameters:
|
|||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
collectionFormat: csv
|
collectionFormat: csv
|
||||||
|
# Core definition
|
||||||
|
attachmentParam:
|
||||||
|
name: attachment
|
||||||
|
in: query
|
||||||
|
description: |
|
||||||
|
**true** enables a web browser to download the file as an attachment.
|
||||||
|
**false** means a web browser may preview the file in a new tab or window, but not
|
||||||
|
download the file.
|
||||||
|
|
||||||
|
You can only set this parameter to **false** if the content type of the file is in the supported list;
|
||||||
|
for example, certain image files and PDF files.
|
||||||
|
|
||||||
|
If the content type is not supported for preview, then a value of **false** is ignored, and
|
||||||
|
the attachment will be returned in the response.
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
# Core definition
|
||||||
|
ifModifiedSinceHeader:
|
||||||
|
name: If-Modified-Since
|
||||||
|
in: header
|
||||||
|
description: |
|
||||||
|
Only returns the content if it has been modified since the date provided.
|
||||||
|
Use the date format defined by HTTP. For example, `Wed, 09 Mar 2016 16:56:34 GMT`.
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
definitions:
|
definitions:
|
||||||
IGNodeEntry:
|
IGNodeEntry:
|
||||||
type: object
|
type: object
|
||||||
|
Reference in New Issue
Block a user