Merge branch 'master' of https://gitlab.alfresco.com/records-management/records-management into feature/RM-4361_ReadRecordsRestAPI

# Conflicts:
#	rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/requests/igCoreAPI/FilePlanComponentAPI.java
#	rm-automation/rm-automation-community-rest-api/src/test/java/org/alfresco/rest/rm/community/base/BaseRestTest.java
This commit is contained in:
Rodica Sutu
2017-01-03 17:48:23 +02:00
37 changed files with 1577 additions and 1244 deletions

View File

@@ -0,0 +1,88 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.core;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* Extends {@link RestProperties} to be able to change/add properties
*
* @author Tuna Aksoy
* @since 2.6
*/
@Configuration
@PropertySource(value = {"classpath:default.properties", "classpath:config.properties"})
@PropertySource(value = "classpath:module.properties", ignoreResourceNotFound = true)
@PropertySource(value = "classpath:local.properties", ignoreResourceNotFound = true)
public class RMRestProperties extends RestProperties
{
@Value ("${alfresco.scheme}")
private String scheme;
@Value ("${alfresco.server}")
private String server;
@Value ("${alfresco.port}")
private String port;
@Value ("${rest.rmPath}")
private String restRmPath;
/**
* @return the scheme
*/
public String getScheme()
{
return this.scheme;
}
/**
* @return the server
*/
public String getServer()
{
return this.server;
}
/**
* @return the port
*/
public String getPort()
{
return this.port;
}
/**
* @return the restRmPath
*/
public String getRestRmPath()
{
return this.restRmPath;
}
}

View File

@@ -0,0 +1,53 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.core;
import org.alfresco.rest.rm.community.requests.igCoreAPI.RestIGCoreAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
/**
* Extends {@link RestWrapper} in order to call IG APIs with our own properties
*
* @author Tuna Aksoy
* @since 2.6
*/
@Primary
@Service
@Scope(value = "prototype")
public class RMRestWrapper extends RestWrapper
{
@Autowired
private RMRestProperties rmRestProperties;
public RestIGCoreAPI withIGCoreAPI()
{
return new RestIGCoreAPI(this, rmRestProperties);
}
}

View File

@@ -0,0 +1,87 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.core;
import org.alfresco.rest.rm.community.requests.igCoreAPI.FilePlanComponentAPI;
import org.alfresco.rest.rm.community.requests.igCoreAPI.RMSiteAPI;
import org.alfresco.rest.rm.community.requests.igCoreAPI.RestIGCoreAPI;
import org.alfresco.utility.data.DataUser;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
/**
* REST API Factory Implementation
*
* @author Tuna Aksoy
* @since 2.6
*/
@Service
@Scope(value = "prototype")
public class RestAPIFactory
{
@Autowired
private DataUser dataUser;
@Autowired
private RMRestWrapper rmRestWrapper;
/**
* @return the rmRestWrapper
*/
public RMRestWrapper getRmRestWrapper()
{
return this.rmRestWrapper;
}
private RestIGCoreAPI getRestIGCoreAPI(UserModel userModel)
{
getRmRestWrapper().authenticateUser(userModel != null ? userModel : dataUser.getAdminUser());
return getRmRestWrapper().withIGCoreAPI();
}
public RMSiteAPI getRMSiteAPI()
{
return getRestIGCoreAPI(null).usingRMSite();
}
public RMSiteAPI getRMSiteAPI(UserModel userModel)
{
return getRestIGCoreAPI(userModel).usingRMSite();
}
public FilePlanComponentAPI getFilePlanComponentsAPI()
{
return getRestIGCoreAPI(null).usingFilePlanComponents();
}
public FilePlanComponentAPI getFilePlanComponentsAPI(UserModel userModel)
{
return getRestIGCoreAPI(userModel).usingFilePlanComponents();
}
}

View File

@@ -37,9 +37,12 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.alfresco.utility.model.TestModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
@@ -51,9 +54,10 @@ import lombok.NoArgsConstructor;
*/
@Builder
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class FilePlanComponent
public class FilePlanComponent extends TestModel
{
@JsonProperty (required = true)
private String id;
@@ -114,5 +118,4 @@ public class FilePlanComponent
@JsonProperty (value = RELATIVE_PATH)
private String relativePath;
}

View File

@@ -26,58 +26,16 @@
*/
package org.alfresco.rest.rm.community.model.fileplancomponents;
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryString;
/**
* File plan component alias enumeration
* File plan component alias
*
* @author Tuna Aksoy
* @since 2.6
*/
public enum FilePlanComponentAlias
public class FilePlanComponentAlias
{
FILE_PLAN_ALIAS("-filePlan-"),
TRANSFERS_ALIAS("-transfers-"),
UNFILED_RECORDS_CONTAINER_ALIAS("-unfiled-"),
HOLDS_ALIAS("-holds-");
private String alias;
private FilePlanComponentAlias(String alias)
{
this.alias = alias;
}
public static final FilePlanComponentAlias getFilePlanComponentAlias(String alias)
{
mandatoryString("alias", alias);
FilePlanComponentAlias result = null;
FilePlanComponentAlias[] values = values();
for (FilePlanComponentAlias filePlanComponentAlias : values)
{
if (filePlanComponentAlias.toString().equals(alias))
{
result = filePlanComponentAlias;
break;
}
}
if (result == null)
{
throw new IllegalArgumentException("Invalid file plan component alias enum value: '" + alias + "'.");
}
return result;
}
/**
* @see java.lang.Enum#toString()
*/
@Override
public String toString()
{
return this.alias;
}
public static final String FILE_PLAN_ALIAS = "-filePlan-";
public static final String TRANSFERS_ALIAS = "-transfers-";
public static final String UNFILED_RECORDS_CONTAINER_ALIAS = "-unfiled-";
public static final String HOLDS_ALIAS = "-holds-";
}

View File

@@ -35,6 +35,7 @@ import lombok.NoArgsConstructor;
/**
* POJO for FilePlanComponent content field
*
* @author Kristijan Conkas
* @since 2.6
*/
@@ -55,5 +56,4 @@ public class FilePlanComponentContent
@JsonProperty (required = true)
private Integer sizeInBytes;
}

View File

@@ -30,11 +30,13 @@ import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanCo
import com.fasterxml.jackson.annotation.JsonProperty;
import org.alfresco.rest.core.RestModels;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.alfresco.rest.core.RestModels;
/**
* POJO for file plan component entry
@@ -44,11 +46,11 @@ import org.alfresco.rest.core.RestModels;
*/
@Builder
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class FilePlanComponentEntry extends RestModels<FilePlanComponent, FilePlanComponentEntry>
{
@JsonProperty(ENTRY)
FilePlanComponent filePlanComponent;
FilePlanComponent filePlanComponentModel;
}

View File

@@ -45,5 +45,4 @@ public class FilePlanComponentIdNamePair
{
public String id;
public String name;
}

View File

@@ -37,7 +37,7 @@ import lombok.NoArgsConstructor;
/**
* POJO for FilePlanComponent path parameter
* <br>
*
* @author Kristijan Conkas
* @since 2.6
*/
@@ -51,5 +51,4 @@ public class FilePlanComponentPath
private String name;
private Boolean isComplete;
private List<FilePlanComponentIdNamePair> elements;
}

View File

@@ -67,7 +67,6 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
public class FilePlanComponentProperties
{
@JsonProperty(PROPERTIES_VITAL_RECORD_INDICATOR)
private Boolean vitalRecord;
@@ -85,28 +84,26 @@ public class FilePlanComponentProperties
@JsonProperty(PROPERTIES_REVIEW_PERIOD)
@JsonSerialize (using = ReviewPeriodSerializer.class)
private ReviewPeriod reviewPeriod;
private FilePlanComponentReviewPeriod reviewPeriod;
@JsonProperty(PROPERTIES_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;
}

View File

@@ -32,7 +32,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
/**
* POJO for the review period
* POJO for the file plan component review period
*
* @author Rodica Sutu
* @since 2.6
@@ -41,7 +41,7 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ReviewPeriod
public class FilePlanComponentReviewPeriod
{
private String periodType;
private String expression;

View File

@@ -26,66 +26,24 @@
*/
package org.alfresco.rest.rm.community.model.fileplancomponents;
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryString;
/**
* File plan component type enumeration
* File plan component type
*
* @author Tuna Aksoy
* @since 2.6
*/
public enum FilePlanComponentType
public class FilePlanComponentType
{
FILE_PLAN_TYPE("rma:filePlan"),
RECORD_CATEGORY_TYPE("rma:recordCategory"),
RECORD_FOLDER_TYPE("rma:recordFolder"),
HOLD_TYPE("rma:hold"),
UNFILED_RECORD_FOLDER_TYPE("rma:unfiledRecordFolder"),
HOLD_CONTAINER_TYPE("rma:holdContainer"),
TRANSFER_TYPE("rma:transfer"),
TRANSFER_CONTAINER_TYPE("rma:transferContainer"),
UNFILED_CONTAINER_TYPE("rma:unfiledRecordContainer"),
FOLDER_TYPE("cm:folder"),
CONTENT_TYPE("cm:content"),
NON_ELECTRONIC_RECORD_TYPE("rma:nonElectronicDocument");
private String type;
private FilePlanComponentType(String type)
{
this.type = type;
}
public static final FilePlanComponentType getFilePlanComponentType(String type)
{
mandatoryString("type", type);
FilePlanComponentType result = null;
FilePlanComponentType[] values = values();
for (FilePlanComponentType filePlanComponentType : values)
{
if (filePlanComponentType.toString().equals(filePlanComponentType))
{
result = filePlanComponentType;
break;
}
}
if (result == null)
{
throw new IllegalArgumentException("Invalid file plan component type enum value: '" + type + "'.");
}
return result;
}
/**
* @see java.lang.Enum#toString()
*/
@Override
public String toString()
{
return this.type;
}
public static final String FILE_PLAN_TYPE = "rma:filePlan";
public static final String RECORD_CATEGORY_TYPE = "rma:recordCategory";
public static final String RECORD_FOLDER_TYPE = "rma:recordFolder";
public static final String HOLD_TYPE = "rma:hold";
public static final String UNFILED_RECORD_FOLDER_TYPE = "rma:unfiledRecordFolder";
public static final String HOLD_CONTAINER_TYPE = "rma:holdContainer";
public static final String TRANSFER_TYPE = "rma:transfer";
public static final String TRANSFER_CONTAINER_TYPE = "rma:transferContainer";
public static final String UNFILED_CONTAINER_TYPE = "rma:unfiledRecordContainer";
public static final String FOLDER_TYPE = "cm:folder";
public static final String CONTENT_TYPE = "cm:content";
public static final String NON_ELECTRONIC_RECORD_TYPE = "rma:nonElectronicDocument";
}

View File

@@ -45,5 +45,4 @@ public class FilePlanComponentUserInfo
{
private String id;
private String displayName;
}

View File

@@ -30,11 +30,13 @@ import static org.alfresco.rest.rm.community.model.site.RMSiteFields.COMPLIANCE;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.alfresco.rest.model.RestSiteModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.alfresco.rest.model.RestSiteModel;
/**
* POJO for RM Site component
@@ -44,11 +46,11 @@ import org.alfresco.rest.model.RestSiteModel;
*/
@Builder
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class RMSite extends RestSiteModel
{
@JsonProperty (value = COMPLIANCE,required = true)
@JsonProperty (value = COMPLIANCE, required = true)
private RMSiteCompliance compliance;
}

View File

@@ -0,0 +1,58 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.requests;
import org.alfresco.rest.core.RMRestWrapper;
import org.alfresco.rest.requests.ModelRequest;
/**
* Extends {@link ModelRequest} to set {@link RMRestWrapper}
*
* @author Tuna Aksoy
* @since 2.6
*/
public abstract class RMModelRequest extends ModelRequest
{
private RMRestWrapper rmRestWrapper;
/**
* @return the rmRestWrapper
*/
protected RMRestWrapper getRMRestWrapper()
{
return this.rmRestWrapper;
}
/**
* @param restWrapper
*/
public RMModelRequest(RMRestWrapper rmRestWrapper)
{
super(rmRestWrapper);
this.rmRestWrapper = rmRestWrapper;
}
}

View File

@@ -24,16 +24,18 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.requests;
package org.alfresco.rest.rm.community.requests.igCoreAPI;
import static com.jayway.restassured.RestAssured.basic;
import static com.jayway.restassured.RestAssured.given;
import static org.alfresco.rest.core.RestRequest.requestWithBody;
import static org.alfresco.rest.core.RestRequest.simpleRequest;
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.CONTENT_TYPE;
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryObject;
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryString;
import static org.alfresco.rest.rm.community.util.PojoUtility.toJson;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.springframework.http.HttpMethod.DELETE;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
@@ -50,25 +52,30 @@ import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
import org.alfresco.rest.core.RestAPI;
import org.alfresco.rest.core.RMRestWrapper;
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.requests.RMModelRequest;
import org.alfresco.utility.model.UserModel;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* File plan component REST API Wrapper
*
* @author Tuna Aksoy
* @author Kristijan Conkas
* @since 2.6
*/
@Component
@Scope(value = "prototype")
public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
public class FilePlanComponentAPI extends RMModelRequest
{
/**
* Constructor
*
* @param restWrapper
*/
public FilePlanComponentAPI(RMRestWrapper rmRestWrapper)
{
super(rmRestWrapper);
}
/**
* Get a file plan component
*
@@ -85,10 +92,31 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
{
mandatoryString("filePlanComponentId", filePlanComponentId);
return usingRestWrapper().processModel(FilePlanComponent.class, simpleRequest(
return getFilePlanComponent(filePlanComponentId, EMPTY);
}
/**
* Get a file plan component
*
* @param filePlanComponentId The id of the file plan component to get
* @param parameters The URL parameters to add
* @return The {@link FilePlanComponent} for the given file plan component id
* @throws Exception for the following cases:
* <ul>
* <li>{@code fileplanComponentId} is not a valid format</li>
* <li>authentication fails</li>
* <li>{@code fileplanComponentId} does not exist</li>
* </ul>
*/
public FilePlanComponent getFilePlanComponent(String filePlanComponentId, String parameters) throws Exception
{
mandatoryString("filePlanComponentId", filePlanComponentId);
return getRMRestWrapper().processModel(FilePlanComponent.class, simpleRequest(
GET,
"fileplan-components/{fileplanComponentId}?{parameters}",
filePlanComponentId, getParameters()
filePlanComponentId,
parameters
));
}
@@ -108,7 +136,7 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
{
mandatoryString("filePlanComponentId", filePlanComponentId);
return usingRestWrapper().processModels(FilePlanComponentsCollection.class, simpleRequest(
return getRMRestWrapper().processModels(FilePlanComponentsCollection.class, simpleRequest(
GET,
"fileplan-components/{fileplanComponentId}/children?{parameters}",
filePlanComponentId, getParameters()
@@ -135,15 +163,41 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
{
mandatoryObject("filePlanComponentProperties", filePlanComponentModel);
mandatoryString("parentId", parentId);
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
POST,
toJson(filePlanComponentModel),
"fileplan-components/{fileplanComponentId}/children?{parameters}",
parentId,
getParameters()));
return createFilePlanComponent(filePlanComponentModel, parentId, EMPTY);
}
/**
* Creates a file plan component with the given properties under the parent node with the given id
*
* @param filePlanComponentModel The properties of the file plan component to be created
* @param parameters The URL parameters to add
* @param parentId The id of the parent where the new file plan component should be created
* @return The {@link FilePlanComponent} with the given properties
* @throws Exception for the following cases:
* <ul>
* <li>{@code fileplanComponentId} is not a valid format</li>
* <li>authentication fails</li>
* <li>current user does not have permission to add children to {@code fileplanComponentId}</li>
* <li>{@code fileplanComponentId} does not exist</li>
* <li>new name clashes with an existing node in the current parent container</li>
* <li>model integrity exception, including node name with invalid characters</li>
* </ul>
*/
public FilePlanComponent createFilePlanComponent(FilePlanComponent filePlanComponentModel, String parentId, String parameters) throws Exception
{
mandatoryObject("filePlanComponentProperties", filePlanComponentModel);
mandatoryString("parentId", parentId);
return getRMRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
POST,
toJson(filePlanComponentModel),
"fileplan-components/{fileplanComponentId}/children?{parameters}",
parentId,
parameters
));
}
/**
* Create electronic record from file resource
* @param electronicRecordModel {@link FilePlanComponent} for electronic record to be created
@@ -156,7 +210,7 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
{
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
@@ -167,53 +221,42 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
*/
public FilePlanComponent createElectronicRecord(FilePlanComponent electronicRecordModel, File recordContent, String parentId) throws Exception
{
mandatoryObject("filePlanComponentProperties", electronicRecordModel);
mandatoryObject("electronicRecordModel", electronicRecordModel);
mandatoryString("parentId", parentId);
if (!electronicRecordModel.getNodeType().equals(FilePlanComponentType.CONTENT_TYPE.toString()))
if (!electronicRecordModel.getNodeType().equals(CONTENT_TYPE))
{
fail("Only electronic records are supported");
}
UserModel currentUser = usingRestWrapper().getTestUser();
/*
UserModel currentUser = getRMRestWrapper().getTestUser();
/*
* For file uploads nodeBodyCreate is ignored hence can't be used. Append all FilePlanComponent fields
* to the request.
*/
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.setAuth(basic(currentUser.getUsername(), currentUser.getPassword()));
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(toJson(electronicRecordModel));
Iterator<String> fieldNames = root.fieldNames();
while (fieldNames.hasNext())
{
String f = fieldNames.next();
try
{
builder.addMultiPart(f, root.get(f).asText(), ContentType.JSON.name());
}
catch (Exception error)
{
LOG.error("Failed to set " + f + " error: " + error);
}
String fieldName = fieldNames.next();
builder.addMultiPart(fieldName, root.get(fieldName).asText(), ContentType.JSON.name());
}
builder.addMultiPart("filedata", recordContent, ContentType.BINARY.name());
/*
* RestWrapper adds some headers which break multipart/form-data uploads and also assumes json POST requests.
* Upload the file using RestAssured library.
*/
Response response = given()
.spec(builder.build())
.when()
.post("fileplan-components/{fileplanComponentId}/children?{parameters}", parentId, getParameters())
.post("fileplan-components/{fileplanComponentId}/children?{parameters}", parentId, getRMRestWrapper().getParameters())
.andReturn();
usingRestWrapper().setStatusCode(Integer.toString(response.getStatusCode()));
LOG.info("electronic record created: " + response.getBody().prettyPrint());
getRMRestWrapper().setStatusCode(Integer.toString(response.getStatusCode()));
/* return a FilePlanComponent object representing Response */
return response.jsonPath().getObject("entry", FilePlanComponent.class);
}
@@ -221,7 +264,7 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
/**
* Updates a file plan component
*
* @param filePlanComponent The properties to be updated
* @param filePlanComponentModel The properties to be updated
* @param filePlanComponentId The id of the file plan component which will be updated
* @param returns The updated {@link FilePlanComponent}
* @throws Exception for the following cases:
@@ -234,17 +277,42 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
* <li>model integrity exception, including node name with invalid characters</li>
* </ul>
*/
public FilePlanComponent updateFilePlanComponent(FilePlanComponent filePlanComponent, String filePlanComponentId) throws Exception
public FilePlanComponent updateFilePlanComponent(FilePlanComponent filePlanComponentModel, String filePlanComponentId) throws Exception
{
mandatoryObject("filePlanComponentProperties", filePlanComponentModel);
mandatoryString("filePlanComponentId", filePlanComponentId);
return updateFilePlanComponent(filePlanComponentModel, filePlanComponentId, EMPTY);
}
/**
* Updates a file plan component
*
* @param filePlanComponentModel The properties to be updated
* @param parameters The URL parameters to add
* @param filePlanComponentId The id of the file plan component which will be updated
* @param returns The updated {@link FilePlanComponent}
* @throws Exception for the following cases:
* <ul>
* <li>the update request is invalid or {@code fileplanComponentId} is not a valid format or {@code filePlanComponentProperties} is invalid</li>
* <li>authentication fails</li>
* <li>current user does not have permission to update {@code fileplanComponentId}</li>
* <li>{@code fileplanComponentId} does not exist</li>
* <li>the updated name clashes with an existing node in the current parent folder</li>
* <li>model integrity exception, including node name with invalid characters</li>
* </ul>
*/
public FilePlanComponent updateFilePlanComponent(FilePlanComponent filePlanComponent, String filePlanComponentId, String parameters) throws Exception
{
mandatoryObject("filePlanComponentProperties", filePlanComponent);
mandatoryString("filePlanComponentId", filePlanComponentId);
return usingRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
return getRMRestWrapper().processModel(FilePlanComponent.class, requestWithBody(
PUT,
toJson(filePlanComponent),
"fileplan-components/{fileplanComponentId}?{parameters}",
filePlanComponentId,
getParameters()
parameters
));
}
@@ -265,11 +333,10 @@ public class FilePlanComponentAPI extends RestAPI<FilePlanComponentAPI>
{
mandatoryString("filePlanComponentId", filePlanComponentId);
usingRestWrapper().processEmptyModel(simpleRequest(
getRMRestWrapper().processEmptyModel(simpleRequest(
DELETE,
"fileplan-components/{fileplanComponentId}",
filePlanComponentId
));
}
}

View File

@@ -24,7 +24,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.requests;
package org.alfresco.rest.rm.community.requests.igCoreAPI;
import static org.alfresco.rest.core.RestRequest.requestWithBody;
import static org.alfresco.rest.core.RestRequest.simpleRequest;
@@ -36,26 +36,27 @@ import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;
import static org.springframework.http.HttpStatus.OK;
import org.alfresco.rest.core.RestAPI;
import org.alfresco.rest.core.RMRestWrapper;
import org.alfresco.rest.rm.community.model.site.RMSite;
import org.alfresco.utility.data.DataUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.alfresco.rest.rm.community.requests.RMModelRequest;
/**
* File plan component REST API Wrapper
* RM Site REST API Wrapper
*
* @author Tuna Aksoy
* @author Rodica Sutu
* @since 2.6
*/
@Component
@Scope (value = "prototype")
public class RMSiteAPI extends RestAPI<RMSiteAPI>
public class RMSiteAPI extends RMModelRequest
{
@Autowired
private DataUser dataUser;
/**
* Constructor
*
* @param rmRestWrapper RM REST Wrapper
*/
public RMSiteAPI(RMRestWrapper rmRestWrapper)
{
super(rmRestWrapper);
}
/**
* Get the RM site
@@ -71,7 +72,7 @@ public class RMSiteAPI extends RestAPI<RMSiteAPI>
*/
public RMSite getSite() throws Exception
{
return usingRestWrapper().processModel(RMSite.class, simpleRequest(
return getRMRestWrapper().processModel(RMSite.class, simpleRequest(
GET,
"ig-sites/rm"
));
@@ -90,13 +91,13 @@ public class RMSiteAPI extends RestAPI<RMSiteAPI>
* <li>Api Response code default Unexpected error</li>
* </ul>
*/
public RMSite createRMSite(RMSite rmSite) throws Exception
public RMSite createRMSite(RMSite rmSiteModel) throws Exception
{
mandatoryObject("rmSiteProperties", rmSite);
mandatoryObject("rmSiteModel", rmSiteModel);
return usingRestWrapper().processModel(RMSite.class, requestWithBody(
return getRMRestWrapper().processModel(RMSite.class, requestWithBody(
POST,
toJson(rmSite),
toJson(rmSiteModel),
"ig-sites"
));
}
@@ -114,7 +115,7 @@ public class RMSiteAPI extends RestAPI<RMSiteAPI>
*/
public void deleteRMSite() throws Exception
{
usingRestWrapper().processEmptyModel(simpleRequest(
getRMRestWrapper().processEmptyModel(simpleRequest(
DELETE,
"ig-sites/rm"
));
@@ -127,20 +128,20 @@ public class RMSiteAPI extends RestAPI<RMSiteAPI>
* @return The updated {@link RMSite}
* @throws Exception for the following cases:
* <ul>
* <li>Api Response code 400 the update request is invalid {@code rmSiteProperties} is invalid</li>
* <li>Api Response code 400 the update request is invalid {@code rmSiteModel} is invalid</li>
* <li>Api Response code 401 If authentication fails</li>
* <li>Api Response code 403 does not have permission to update {@code RMSite}</li>
* <li>Api Response code 404 {@code RMSite} does not exist</li>
* <li>Api Response code 404 {@code RMSiteModel} does not exist</li>
* <li>Api Response code default Unexpected error,model integrity exception</li>
* </ul>
*/
public RMSite updateRMSite(RMSite rmSiteProperties) throws Exception
public RMSite updateRMSite(RMSite rmSiteModel) throws Exception
{
mandatoryObject("rmSiteProperties", rmSiteProperties);
mandatoryObject("rmSiteProperties", rmSiteModel);
return usingRestWrapper().processModel(RMSite.class, requestWithBody(
return getRMRestWrapper().processModel(RMSite.class, requestWithBody(
PUT,
toJson(rmSiteProperties),
toJson(rmSiteModel),
"ig-sites/rm"
));
}
@@ -159,8 +160,7 @@ public class RMSiteAPI extends RestAPI<RMSiteAPI>
*/
public boolean existsRMSite() throws Exception
{
usingRestWrapper().authenticateUser(dataUser.getAdminUser());
getSite();
return usingRestWrapper().getStatusCode().equals(OK.toString());
return getRMRestWrapper().getStatusCode().equals(OK.toString());
}
}

View File

@@ -24,52 +24,62 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.requests;
package org.alfresco.rest.rm.community.requests.igCoreAPI;
import static com.jayway.restassured.RestAssured.given;
import static org.jglue.fluentjson.JsonBuilderFactory.buildObject;
import com.google.gson.JsonObject;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
import com.jayway.restassured.specification.RequestSpecification;
import org.alfresco.dataprep.AlfrescoHttpClient;
import org.alfresco.dataprep.AlfrescoHttpClientFactory;
import org.alfresco.dataprep.UserService;
import org.alfresco.rest.core.RestAPI;
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponent;
import org.alfresco.utility.data.DataUser;
import org.alfresco.utility.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* RM user management API
*
*
* @author Kristijan Conkas
* @since 2.6
*/
// FIXME: As of December 2016 there is no v1-style API for managing RM users and users'
// roles. Until such APIs have become available, methods in this class are just proxies to
// FIXME: As of December 2016 there is no v1-style API for managing RM users and users'
// roles/permissions. Until such APIs have become available, methods in this class are just proxies to
// "old-style" API calls.
@Component
@Scope (value = "prototype")
public class RMUserAPI extends RestAPI<RMUserAPI>
{
@Autowired
private UserService userService;
@Autowired
private DataUser dataUser;
@Autowired
private AlfrescoHttpClientFactory alfrescoHttpClientFactory;
public void assignRoleToUser(String userName, String userRole) throws Exception
{
// get an "old-style" REST API client
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
// override v1 baseURI and basePath
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri(client.getApiUrl())
.setBasePath("/")
.build();
Response response = given()
.spec(spec)
.log().all()
@@ -83,4 +93,61 @@ public class RMUserAPI extends RestAPI<RMUserAPI>
.andReturn();
usingRestWrapper().setStatusCode(Integer.toString(response.getStatusCode()));
}
/**
* Helper method to add permission on a component to user
* @param component {@link FilePlanComponent} on which permission should be given
* @param user {@link UserModel} for a user to be granted permission
* @param permission {@link UserPermissions} to be granted
*/
public void addUserPermission(FilePlanComponent component, UserModel user, String permission)
{
// get an "old-style" REST API client
AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
JsonObject bodyJson = buildObject()
.addArray("permissions")
.addObject()
.add("authority", user.getUsername())
.add("role", permission)
.end()
.getJson();
// override v1 baseURI and basePath
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri(client.getApiUrl())
.setBasePath("/")
.build();
// execute an "old-style" API call
Response response = given()
.spec(spec)
.auth().basic(dataUser.getAdminUser().getUsername(), dataUser.getAdminUser().getPassword())
.contentType(ContentType.JSON)
.body(bodyJson.toString())
.pathParam("nodeId", component.getId())
.log().all()
.when()
.post("/node/workspace/SpacesStore/{nodeId}/rmpermissions")
.prettyPeek()
.andReturn();
usingRestWrapper().setStatusCode(Integer.toString(response.getStatusCode()));
}
/**
* Creates a user with the given name using the old APIs
*
* @param userName The user name
* @return <code>true</code> if the user was created successfully, <code>false</code> otherwise.
*/
public boolean createUser(String userName)
{
return userService.create(dataUser.getAdminUser().getUsername(),
dataUser.getAdminUser().getPassword(),
userName,
"password",
"default@alfresco.com",
userName,
userName);
}
}

View File

@@ -0,0 +1,80 @@
/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.rm.community.requests.igCoreAPI;
import static java.lang.Integer.parseInt;
import static java.lang.String.format;
import com.jayway.restassured.RestAssured;
import org.alfresco.rest.core.RMRestProperties;
import org.alfresco.rest.core.RMRestWrapper;
import org.alfresco.rest.rm.community.requests.RMModelRequest;
/**
* Defines the entire IG Core API
* {@link http://host:port/ig-api-explorer} select "IG Core API"
*
* @author Tuna Aksoy
* @since 2.6
*/
public class RestIGCoreAPI extends RMModelRequest
{
/**
* Constructor
*
* @param rmRestWrapper RM REST Wrapper
* @param rmRestProperties RM REST Properties
*/
public RestIGCoreAPI(RMRestWrapper rmRestWrapper, RMRestProperties rmRestProperties)
{
super(rmRestWrapper);
RestAssured.baseURI = format("%s://%s", rmRestProperties.getScheme(), rmRestProperties.getServer());
RestAssured.port = parseInt(rmRestProperties.getPort());
RestAssured.basePath = rmRestProperties.getRestRmPath();
}
/**
* Provides DSL on all REST calls under <code>ig-sites/rm/...</code> API path
*
* @return {@link RMSiteAPI}
*/
public RMSiteAPI usingRMSite()
{
return new RMSiteAPI(getRMRestWrapper());
}
/**
* Provides DSL on all REST calls under <code>fileplan-components/...</code> API path
*
* @return {@link FilePlanComponentAPI}
*/
public FilePlanComponentAPI usingFilePlanComponents()
{
return new FilePlanComponentAPI(getRMRestWrapper());
}
}

View File

@@ -57,7 +57,6 @@ public class PojoUtility
{
//return the json object
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(model);
}
catch (JsonGenerationException e)
{

View File

@@ -33,8 +33,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.alfresco.rest.rm.community.model.fileplancomponents.ReviewPeriod;
import org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentReviewPeriod;
/**
* Utility class for serializing the Review Period type
@@ -42,9 +41,8 @@ import org.alfresco.rest.rm.community.model.fileplancomponents.ReviewPeriod;
* @author Rodica Sutu
* @since 2.6
*/
public class ReviewPeriodSerializer extends JsonSerializer<ReviewPeriod>
public class ReviewPeriodSerializer extends JsonSerializer<FilePlanComponentReviewPeriod>
{
/**
* @param value The Review Period value that is being serialized.
* @param gen Jackson utility is responsible for writing JSON
@@ -53,12 +51,9 @@ public class ReviewPeriodSerializer extends JsonSerializer<ReviewPeriod>
* @throws JsonProcessingException
*/
@Override
public void serialize(ReviewPeriod value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException
public void serialize(FilePlanComponentReviewPeriod value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException
{
//create the custom string value for the Review Period type
gen.writeString(new StringBuilder().append(value.getPeriodType()).append("|").append(value.getExpression()).toString());
}
}

View File

@@ -0,0 +1,2 @@
alfresco.server=localhost
rest.rmPath=alfresco/api/-default-/public/ig/versions/1