Merge branch 'master' of git.alfresco.com:records-management/records-management into RM-4431_CompleteRecordActionRestAPI

This commit is contained in:
Sara Aspery
2017-06-23 16:40:00 +01:00
6 changed files with 250 additions and 119 deletions

View File

@@ -24,6 +24,7 @@
<connection>scm:git:https://git.alfresco.com/records-management/records-management.git</connection>
<developerConnection>scm:git:https://git.alfresco.com/records-management/records-management.git</developerConnection>
<url>https://git.alfresco.com/records-management/records-management</url>
<tag>HEAD</tag>
</scm>
<issueManagement>

View File

@@ -138,6 +138,7 @@
<property name="extendedSecurityService" ref="ExtendedSecurityService" />
<property name="recordService" ref="RecordService" />
<property name="dispositionService" ref="DispositionService" />
<property name="quickShareService" ref="QuickShareService"/>
</bean>
<bean id="rma.recordComponentIdentifier" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.RecordComponentIdentifierAspect" parent="rm.baseBehaviour">

View File

@@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.model.QuickShareModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies;
import org.alfresco.module.org_alfresco_module_rm.model.behaviour.AbstractDisposableItem;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
@@ -48,7 +49,9 @@ import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.quickshare.QuickShareService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -68,6 +71,7 @@ import org.springframework.extensions.surf.util.I18NUtil;
)
public class RecordAspect extends AbstractDisposableItem
implements NodeServicePolicies.OnCreateChildAssociationPolicy,
NodeServicePolicies.BeforeAddAspectPolicy,
RecordsManagementPolicies.OnCreateReference,
RecordsManagementPolicies.OnRemoveReference,
NodeServicePolicies.OnMoveNodePolicy,
@@ -87,6 +91,9 @@ public class RecordAspect extends AbstractDisposableItem
/** record service */
protected RecordService recordService;
/** quickShare service */
private QuickShareService quickShareService;
/** I18N */
private static final String MSG_CANNOT_UPDATE_RECORD_CONTENT = "rm.service.update-record-content";
@@ -114,6 +121,15 @@ public class RecordAspect extends AbstractDisposableItem
this.recordService = recordService;
}
/**
*
* @param quickShareService
*/
public void setQuickShareService(QuickShareService quickShareService)
{
this.quickShareService = quickShareService;
}
/**
* Behaviour to ensure renditions have the appropriate extended security.
*
@@ -359,4 +375,30 @@ public class RecordAspect extends AbstractDisposableItem
throw new IntegrityException(I18NUtil.getMessage(MSG_CANNOT_UPDATE_RECORD_CONTENT), null);
}
}
/**
* Behaviour to remove the shared link before declare a record
*
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeAddAspectPolicy#beforeAddAspect(org.alfresco.service.cmr.repository.NodeRef,
* org.alfresco.service.namespace.QName)
*/
@Override
@Behaviour(kind = BehaviourKind.CLASS, notificationFrequency = NotificationFrequency.FIRST_EVENT)
public void beforeAddAspect(final NodeRef nodeRef, final QName aspectTypeQName)
{
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
@Override
public Void doWork()
{
String sharedId = (String) nodeService.getProperty(nodeRef, QuickShareModel.PROP_QSHARE_SHAREDID);
if (sharedId != null)
{
quickShareService.unshareContent(sharedId);
}
return null;
}
}, AuthenticationUtil.getSystemUserName());
}
}

View File

@@ -27,12 +27,14 @@
package org.alfresco.module.org_alfresco_module_rm.test.integration.record;
import org.alfresco.model.QuickShareModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.quickshare.QuickShareService;
import org.alfresco.service.cmr.security.AccessStatus;
/**
@@ -42,12 +44,25 @@ import org.alfresco.service.cmr.security.AccessStatus;
*/
public class CreateInplaceRecordTest extends BaseRMTestCase
{
private QuickShareService quickShareService;
@Override
protected boolean isCollaborationSiteTest()
{
return true;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#initServices()
*/
@Override
protected void initServices()
{
super.initServices();
quickShareService = (QuickShareService) applicationContext.getBean("quickShareService");
}
/**
* Given a document in a collaboration site
* When the document is declared by a site collaborator
@@ -185,4 +200,49 @@ public class CreateInplaceRecordTest extends BaseRMTestCase
}
});
}
/**
* Given a shared document in a collaboration site
* When the document is declared as record by a site collaborator
* Then the document becomes a record and is not shared anymore
*/
public void testCreateInplaceRecordFromCollabSiteRemovesSharedLink()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
public void given()
{
// Check that the document is not a record
assertFalse("The document should not be a record", recordService.isRecord(dmDocument));
quickShareService.shareContent(dmDocument);
// Check the document is shared
assertTrue("The document is shared", nodeService.hasAspect(dmDocument, QuickShareModel.ASPECT_QSHARE));
}
public void when()
{
// Declare the document as a record
AuthenticationUtil.runAs(new RunAsWork<Void>()
{
public Void doWork() throws Exception
{
// Declare record
recordService.createRecord(filePlan, dmDocument);
return null;
}
}, dmCollaborator);
}
public void then()
{
// Check that the document is a record now
assertTrue("The document should now be a record", recordService.isRecord(dmDocument));
// Check that the record is not shared anymore
assertFalse("The document should not be shared anymore", nodeService.hasAspect(dmDocument, QuickShareModel.ASPECT_QSHARE));
}
});
}
}

View File

@@ -46,11 +46,10 @@ paths:
- gs-sites
summary: Create the Records Management (RM) site
description: |
**Note:** this endpoint is available in Records Management 2.6 and newer versions.
Creates the RM site with the given details.
**Note:** the id of a site cannot be updated once the site has been created.
**Note:** The default site id is rm and the default site name is Records Management. The id of a site cannot be updated once the site has been created.
For example, to create an RM site named "Records Management" with "Records Management Description" as description, the following body could be used:
```JSON
@@ -62,7 +61,7 @@ paths:
The creator will be added as a member with Site Manager role.
When you create the RM site, the **filePlan** structure is also created.
When you create the RM site, the **filePlan** structure is also created including special containers, such as containers for transfers, holds and, unfiled records.
operationId: createRMSite
produces:
@@ -102,7 +101,6 @@ paths:
- gs-sites
summary: Get the Records Management (RM) site
description: |
**Note:** this endpoint is available in Records Management 2.6 and newer versions.
Gets information for RM site.
@@ -133,7 +131,6 @@ paths:
- gs-sites
summary: Delete the Records Management (RM) site
description: |
**Note:** this endpoint is available in Records Management 2.6 and newer versions.
Deletes the RM site.
operationId: deleteRMSite
@@ -161,7 +158,6 @@ paths:
- gs-sites
summary: Update the Records Management (RM) site
description: |
**Note:** this endpoint is available in Records Management 2.6 and newer versions.
Update the details for the RM site. Site Manager or other (site) admin can update title or description.
@@ -795,7 +791,7 @@ paths:
delete:
tags:
- unfiled-record-folders
summary : Delete an unfiled record folder
summary : Delete an unfiled record folder. Deleted file plan components cannot be recovered, they are deleted permanently.
description: |
Deletes the unfiled record folder **unfiledRecordFolderId**.
operationId: deleteUnfiledRecordFolder
@@ -1403,7 +1399,7 @@ paths:
- record-folders
summary : Delete a record folder
description: |
Deletes record folder **recordFolderId**.
Deletes record folder **recordFolderId**. Deleted file plan components cannot be recovered, they are deleted permanently.
operationId: deleteRecordFolder
parameters:
- $ref: '#/parameters/recordFolderIdParam'
@@ -1661,7 +1657,7 @@ paths:
- $ref: '#/parameters/fieldsParam'
- in: body
name: recordBodyUpdate
description: The node information to update.
description: The record information to update.
required: true
schema:
$ref: '#/definitions/FilePlanComponentBodyUpdate'
@@ -1694,7 +1690,7 @@ paths:
- records
summary : Delete a record
description: |
Deletes the record **recordId**.
Deletes the record **recordId**. Deleted file plan components cannot be recovered, they are deleted permanently.
operationId: deleteRecord
parameters:
- $ref: '#/parameters/recordIdParam'
@@ -1756,7 +1752,7 @@ paths:
description: |
Files the record **recordId** in the target record folder.
You can specify the target record folder by providing its id **targetParentId**
You need to specify the target record folder by providing its id **targetParentId**
If the record is already filed, a link to the target record folder is created.
@@ -1846,7 +1842,7 @@ paths:
tags:
- files
summary: Declare as record
description: Declares the file **fileId** in the unfiled records container.
description: Declares the file **fileId** in the unfiled records container. The original file is moved to the Records Management site and a secondary parent association is created in the file's original site.
operationId: declareRecord
parameters:
- name: fileId

View File

@@ -1,10 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="max-age=0"/>
<meta http-equiv="cache-control" content="no-cache"/>
<meta http-equiv="expires" content="0"/>
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT"/>
<meta http-equiv="pragma" content="no-cache"/>
<title>Alfresco Governance Services REST API Explorer</title>
<link rel="shortcut icon" href="https://cdn-www.alfresco.com/sites/www.alfresco.com/themes/alfrescodotcom/favicon.ico" />
<link rel="shortcut icon"
href="https://cdn-www.alfresco.com/sites/www.alfresco.com/themes/alfrescodotcom/favicon.ico"/>
<link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
@@ -13,10 +18,18 @@
<link href='css/alfresco.css' media='screen' rel='stylesheet' type='text/css'/>
<!-- Google Tag Manager -->
<script>
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(),
event: 'gtm.js'
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-W4HV22');
</script>
<!-- End Google Tag Manager -->
@@ -65,15 +78,27 @@
});
function addAuthorization() {
var username = $('#input_username').val();
var password = $('#input_password').val();
if (username.trim() != "" && password.trim() != "") {
var cacheA = new SwaggerClient.ApiKeyAuthorization("If-Modified-Since", "Mon, 26 Jul 1997 05:00:00 GMT", "header"),
cacheB = new SwaggerClient.ApiKeyAuthorization("Cache-Control", "no-cache", "header"),
cacheC = new SwaggerClient.ApiKeyAuthorization("Pragma", "no-cache", "header"),
username = $('#input_username').val(),
password = $('#input_password').val();
if (username.trim() != "" && password.trim() != "")
{
var basicAuth = new SwaggerClient.PasswordAuthorization(username, password);
window.swaggerUi.api.clientAuthorizations.remove("basicAuth");
window.swaggerUi.api.clientAuthorizations.add("basicAuth", basicAuth);
log("authorization added: username = " + username + ", auth = " + basicAuth);
}
window.swaggerUi.api.clientAuthorizations.add("cacheA", cacheA);
window.swaggerUi.api.clientAuthorizations.add("cacheB", cacheB);
window.swaggerUi.api.clientAuthorizations.add("cacheC", cacheC);
}
$('#input_username').change(addAuthorization);
$('#input_password').change(addAuthorization);
@@ -86,7 +111,8 @@
});
function log() {
if ('console' in window) {
if ('console' in window)
{
console.log.apply(console, arguments);
}
}
@@ -96,7 +122,10 @@
<body class="swagger-section">
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W4HV22" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W4HV22" height="0" width="0"
style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
<div id='header'>
<div class="swagger-ui-wrap">
@@ -107,8 +136,10 @@
<option value="definitions/gs-core-api.yaml">GS Core API</option>
</select>
</div>
<div class="input"><input alt="Username" type="text" name="username" id="input_username" placeholder="username" size="10" value="admin"></div>
<div class="input"><input alt="Password" type="password" name="password" id="input_password" placeholder="password" size="10" value="admin"></div>
<div class="input"><input alt="Username" type="text" name="username" id="input_username" placeholder="username"
size="10" value="admin"></div>
<div class="input"><input alt="Password" type="password" name="password" id="input_password"
placeholder="password" size="10" value="admin"></div>
</form>
</div>
</div>