From 577173c2b69ed8426a90c10b5744743eea501fc5 Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Mon, 26 Sep 2016 17:32:53 +0300 Subject: [PATCH 1/9] RM-4097: added fix for both issues --- .../rm-webscript-context.xml | 1 + .../roles/rm-dynamicauthorities.get.desc.xml | 3 +- .../scripts/roles/DynamicAuthoritiesGet.java | 450 ++++++++++++++---- .../test/util/BaseWebScriptUnitTest.java | 10 +- .../roles/DynamicAuthoritiesGetUnitTest.java | 109 ++++- 5 files changed, 439 insertions(+), 134 deletions(-) diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index da41dd3d0e..bf87988d70 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -596,6 +596,7 @@ + diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml b/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml index bd4aee74a0..49b7ca51a0 100644 --- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml +++ b/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml @@ -4,9 +4,10 @@ Removes dynamic authorities from in place records created in previous verssions.
URL parameter batchsize is mandatory, and represents the number of records that are processed in one transaction.
URL parameter maxProcessedRecords is optional, and represents the maximum number of records that will be processed in one request.
+ URL parameter export is optional, and if the it's value is true, will export the processed records into a csv file.
]]> - /api/rm/rm-dynamicauthorities?batchsize={batchsize}&maxProcessedRecords={maxProcessedRecords?} + /api/rm/rm-dynamicauthorities?batchsize={batchsize}&maxProcessedRecords={maxProcessedRecords?}&export={export?} argument admin required diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java index b023dcf45e..c7da809e5c 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java @@ -16,14 +16,24 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ + package org.alfresco.repo.web.scripts.roles; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.HttpServletResponse; + import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; @@ -33,19 +43,24 @@ import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.patch.PatchDAO; import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.web.scripts.content.ContentStreamer; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.Pair; +import org.alfresco.util.TempFileProvider; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Cache; -import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.Format; import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; /** * Webscript used for removing dynamic authorities from the records. @@ -54,7 +69,7 @@ import org.springframework.extensions.webscripts.WebScriptRequest; * @since 2.3.0.7 */ @SuppressWarnings("deprecation") -public class DynamicAuthoritiesGet extends DeclarativeWebScript implements RecordsManagementModel +public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsManagementModel { private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0."; private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN"; @@ -64,20 +79,19 @@ public class DynamicAuthoritiesGet extends DeclarativeWebScript implements Recor private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid."; private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory"; private static final String SUCCESS_STATUS = "success"; - private static final String FAILED_STATUS = "failed"; /** * The logger */ private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class); private static final String BATCH_SIZE = "batchsize"; private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords"; + private static final String PARAM_EXPORT = "export"; private static final String MODEL_STATUS = "responsestatus"; private static final String MODEL_MESSAGE = "message"; private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records."; private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records."; private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed."; - /** services */ private PatchDAO patchDAO; private NodeDAO nodeDAO; @@ -86,54 +100,57 @@ public class DynamicAuthoritiesGet extends DeclarativeWebScript implements Recor private PermissionService permissionService; private ExtendedSecurityService extendedSecurityService; private TransactionService transactionService; - + /** Content Streamer */ + protected ContentStreamer contentStreamer; /** service setters */ - public void setPatchDAO(PatchDAO patchDAO) { this.patchDAO = patchDAO; } - public void setNodeDAO(NodeDAO nodeDAO) { this.nodeDAO = nodeDAO; } - public void setQnameDAO(QNameDAO qnameDAO) { this.qnameDAO = qnameDAO; } - public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } - public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; } - public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) { this.extendedSecurityService = extendedSecurityService; } - public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; } + public void setPatchDAO(PatchDAO patchDAO) + { + this.patchDAO = patchDAO; + } - @Override - protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) + { + this.extendedSecurityService = extendedSecurityService; + } + + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + public void setContentStreamer(ContentStreamer contentStreamer) + { + this.contentStreamer = contentStreamer; + } + + protected Map buildModel(WebScriptRequest req, WebScriptResponse res) throws IOException { Map model = new HashMap(); - String batchSizeStr = req.getParameter(BATCH_SIZE); - String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS); - - Long size = 0L; - if (StringUtils.isBlank(batchSizeStr)) - { - model.put(MODEL_STATUS, FAILED_STATUS); - model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_MANDATORY); - logger.info(MESSAGE_BATCHSIZE_IS_MANDATORY); - return model; - } - try - { - size = Long.parseLong(batchSizeStr); - if(size <= 0) - { - model.put(MODEL_STATUS, FAILED_STATUS); - model.put(MODEL_MESSAGE, MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO); - logger.info(MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO); - return model; - } - } - catch(NumberFormatException ex) - { - model.put(MODEL_STATUS, FAILED_STATUS); - model.put(MODEL_MESSAGE, MESSAGE_BATCHSIZE_IS_INVALID); - logger.info(MESSAGE_BATCHSIZE_IS_INVALID); - return model; - } - final Long batchSize = size; + final Long batchSize = getBatchSizeParameter(req); // get the max node id and the extended security aspect Long maxNodeId = patchDAO.getMaxAdmNodeID(); final Pair recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY); - if(recordAspectPair == null) + if (recordAspectPair == null) { model.put(MODEL_STATUS, SUCCESS_STATUS); model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS); @@ -141,64 +158,29 @@ public class DynamicAuthoritiesGet extends DeclarativeWebScript implements Recor return model; } - //default total number of records to be processed to batch size value - Long totalNumberOfRecordsToProcess = batchSize; - if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) + Long totalNumberOfRecordsToProcess = getMaxToProccessParameter(req, batchSize); + + boolean attach = getExportParameter(req); + + File file = TempFileProvider.createTempFile("processedNodes_", ".csv"); + FileWriter writer = new FileWriter(file); + BufferedWriter out = new BufferedWriter(writer); + List processedNodes = new ArrayList(); + try { - try - { - totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); - } - catch(NumberFormatException ex) - { - //do nothing here, the value will remain 0L in this case - } + processedNodes = processNodes(batchSize, maxNodeId, recordAspectPair, totalNumberOfRecordsToProcess, out, + attach); + } + finally + { + out.close(); } - final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; - final List processedNodes = new ArrayList(); - logger.info(MESSAGE_PROCESSING_BEGIN); - // by batch size - for (Long i = 0L; i < maxNodeId; i+=batchSize) - { - if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - final Long currentIndex = i; - - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - // get the nodes with the extended security aspect applied - List nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, currentIndex + batchSize); - - // process each one - for (Long nodeId : nodeIds) - { - if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); - String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); - processNode(record); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); - processedNodes.add(record); - } - - return null; - } - }, - false, // read only - true); // requires new - } - logger.info(MESSAGE_PROCESSING_END); int processedNodesSize = processedNodes.size(); + String message = ""; - if(totalNumberOfRecordsToProcess == 0 || (totalNumberOfRecordsToProcess > 0 && processedNodesSize < totalNumberOfRecordsToProcess)) + if (totalNumberOfRecordsToProcess == 0 + || (totalNumberOfRecordsToProcess > 0 && processedNodesSize < totalNumberOfRecordsToProcess)) { message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedNodesSize); } @@ -209,20 +191,284 @@ public class DynamicAuthoritiesGet extends DeclarativeWebScript implements Recor model.put(MODEL_STATUS, SUCCESS_STATUS); model.put(MODEL_MESSAGE, message); logger.info(message); + + if (attach) + { + try + { + String fileName = file.getName(); + contentStreamer.streamContent(req, res, file, null, attach, fileName, model); + model = null; + } + finally + { + if (file != null) + { + file.delete(); + } + } + } return model; } + /** + * Get export parameter from the request + * @param req + * @return + */ + protected boolean getExportParameter(WebScriptRequest req) + { + boolean attach = false; + String export = req.getParameter(PARAM_EXPORT); + if (export != null && Boolean.parseBoolean(export)) + { + attach = true; + } + return attach; + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.web.scripts.content.StreamContent#execute(org.springframework.extensions.webscripts. + * WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) + */ + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + // retrieve requested format + String format = req.getFormat(); + + try + { + String mimetype = getContainer().getFormatRegistry().getMimeType(req.getAgent(), format); + if (mimetype == null) + { + throw new WebScriptException("Web Script format '" + format + "' is not registered"); + } + + // construct model for script / template + Status status = new Status(); + Cache cache = new Cache(getDescription().getRequiredCache()); + Map model = buildModel(req, res); + if (model == null) + { + return; + } + model.put("status", status); + model.put("cache", cache); + + Map templateModel = createTemplateParameters(req, res, model); + + // render output + int statusCode = status.getCode(); + if (statusCode != HttpServletResponse.SC_OK && !req.forceSuccessStatus()) + { + if (logger.isDebugEnabled()) + { + logger.debug("Force success status header in response: " + req.forceSuccessStatus()); + logger.debug("Setting status " + statusCode); + } + res.setStatus(statusCode); + } + + // apply location + String location = status.getLocation(); + if (location != null && location.length() > 0) + { + if (logger.isDebugEnabled()) logger.debug("Setting location to " + location); + res.setHeader(WebScriptResponse.HEADER_LOCATION, location); + } + + // apply cache + res.setCache(cache); + + String callback = null; + if (getContainer().allowCallbacks()) + { + callback = req.getJSONCallback(); + } + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + if (logger.isDebugEnabled()) logger.debug("Rendering JSON callback response: content type=" + + Format.JAVASCRIPT.mimetype() + ", status=" + statusCode + ", callback=" + callback); + + // NOTE: special case for wrapping JSON results in a javascript function callback + res.setContentType(Format.JAVASCRIPT.mimetype() + ";charset=UTF-8"); + res.getWriter().write((callback + "(")); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Rendering response: content type=" + mimetype + ", status=" + statusCode); + + res.setContentType(mimetype + ";charset=UTF-8"); + } + + // render response according to requested format + renderFormatTemplate(format, templateModel, res.getWriter()); + + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + // NOTE: special case for wrapping JSON results in a javascript function callback + res.getWriter().write(")"); + } + } + catch (Throwable e) + { + if (logger.isDebugEnabled()) + { + StringWriter stack = new StringWriter(); + e.printStackTrace(new PrintWriter(stack)); + logger.debug("Caught exception; decorating with appropriate status template : " + stack.toString()); + } + + throw createStatusException(e, req, res); + } + } + + protected void renderFormatTemplate(String format, Map model, Writer writer) + { + format = (format == null) ? "" : format; + + String templatePath = getDescription().getId() + "." + format; + + if (logger.isDebugEnabled()) logger.debug("Rendering template '" + templatePath + "'"); + + renderTemplate(templatePath, model, writer); + } + + /** + * Obtain maximum of the records to be processed from the request if it is specified or bachsize value otherwise + * + * @param req + * @return maximum of the records to be processed from the request if it is specified or bachsize value otherwise + */ + protected Long getMaxToProccessParameter(WebScriptRequest req, final Long batchSize) + { + String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS); + // default total number of records to be processed to batch size value + Long totalNumberOfRecordsToProcess = batchSize; + if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) + { + try + { + totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); + } + catch (NumberFormatException ex) + { + // do nothing here, the value will remain 0L in this case + } + } + return totalNumberOfRecordsToProcess; + } + + /** + * Obtain batchsize parameter from the request. + * + * @param req + * @return batchsize parameter from the request + */ + protected Long getBatchSizeParameter(WebScriptRequest req) + { + String batchSizeStr = req.getParameter(BATCH_SIZE); + Long size = 0L; + if (StringUtils.isBlank(batchSizeStr)) + { + logger.info(MESSAGE_BATCHSIZE_IS_MANDATORY); + throw new WebScriptException(Status.STATUS_BAD_REQUEST, MESSAGE_BATCHSIZE_IS_MANDATORY); + } + try + { + size = Long.parseLong(batchSizeStr); + if (size <= 0) + { + logger.info(MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO); + throw new WebScriptException(Status.STATUS_BAD_REQUEST, MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO); + } + } + catch (NumberFormatException ex) + { + logger.info(MESSAGE_BATCHSIZE_IS_INVALID); + throw new WebScriptException(Status.STATUS_BAD_REQUEST, MESSAGE_BATCHSIZE_IS_INVALID); + } + return size; + } + + /** + * Process nodes all nodes or the maximum number of nodes specified by batchsize or totalNumberOfRecordsToProcess + * parameters + * + * @param batchSize + * @param maxNodeId + * @param recordAspectPair + * @param totalNumberOfRecordsToProcess + * @return the list of processed nodes + */ + protected List processNodes(final Long batchSize, Long maxNodeId, final Pair recordAspectPair, + Long totalNumberOfRecordsToProcess, final BufferedWriter out, final boolean attach) + { + final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; + final List processedNodes = new ArrayList(); + logger.info(MESSAGE_PROCESSING_BEGIN); + // by batch size + for (Long i = 0L; i < maxNodeId; i += batchSize) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + final Long currentIndex = i; + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // get the nodes with the extended security aspect applied + List nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, + currentIndex + batchSize); + + // process each one + for (Long nodeId : nodeIds) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); + String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); + processNode(record); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); + processedNodes.add(record); + if (attach) + { + out.write(recordName); + out.write(","); + out.write(record.toString()); + out.write("\n"); + } + } + + return null; + } + }, false, // read only + true); // requires new + } + logger.info(MESSAGE_PROCESSING_END); + return processedNodes; + } + /** * Process each node * * @param nodeRef */ - @SuppressWarnings({ "unchecked"}) + @SuppressWarnings({ "unchecked" }) private void processNode(NodeRef nodeRef) { // get the reader/writer data - Map readers = (Map)nodeService.getProperty(nodeRef, PROP_READERS); - Map writers = (Map)nodeService.getProperty(nodeRef, PROP_WRITERS); + Map readers = (Map) nodeService.getProperty(nodeRef, PROP_READERS); + Map writers = (Map) nodeService.getProperty(nodeRef, PROP_WRITERS); // remove extended security aspect nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY); @@ -232,7 +478,7 @@ public class DynamicAuthoritiesGet extends DeclarativeWebScript implements Recor permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER); // if record then ... - if (nodeService.hasAspect(nodeRef, ASPECT_RECORD)) + if (nodeService.hasAspect(nodeRef, ASPECT_RECORD) && readers != null && writers != null) { // re-set extended security via API extendedSecurityService.set(nodeRef, readers.keySet(), writers.keySet()); diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java index 2a0f18a927..79f9843585 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseWebScriptUnitTest.java @@ -31,8 +31,8 @@ import org.json.JSONObject; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.extensions.surf.util.Content; +import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Container; -import org.springframework.extensions.webscripts.DeclarativeWebScript; import org.springframework.extensions.webscripts.Description; import org.springframework.extensions.webscripts.Description.RequiredCache; import org.springframework.extensions.webscripts.DescriptionExtension; @@ -68,8 +68,8 @@ public abstract class BaseWebScriptUnitTest extends BaseUnitTest /** * @return declarative webscript */ - protected abstract DeclarativeWebScript getWebScript(); - + protected abstract AbstractWebScript getWebScript(); + /** * @return classpath location of webscript template */ @@ -136,7 +136,7 @@ public abstract class BaseWebScriptUnitTest extends BaseUnitTest */ protected String executeWebScript(Map parameters, String content) throws Exception { - DeclarativeWebScript webScript = getWebScript(); + AbstractWebScript webScript = getWebScript(); String template = getWebScriptTemplate(); // initialise webscript @@ -158,7 +158,7 @@ public abstract class BaseWebScriptUnitTest extends BaseUnitTest * @return {@link WebScriptRequest} mocked web script request */ @SuppressWarnings("rawtypes") - protected WebScriptRequest getMockedWebScriptRequest(DeclarativeWebScript webScript, final Map parameters, String content) throws Exception + protected WebScriptRequest getMockedWebScriptRequest(AbstractWebScript webScript, final Map parameters, String content) throws Exception { Match match = new Match(null, parameters, null, webScript); org.springframework.extensions.webscripts.Runtime mockedRuntime = mock(org.springframework.extensions.webscripts.Runtime.class); diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index c18ed9c9cf..80e65f5984 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -23,6 +23,7 @@ import static java.util.Collections.emptyMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; @@ -55,6 +56,7 @@ import org.alfresco.repo.domain.patch.PatchDAO; import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.web.scripts.content.ContentStreamer; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.PermissionService; @@ -69,7 +71,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.springframework.extensions.webscripts.DeclarativeWebScript; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; /** * DynamicAuthoritiesGet Unit Test @@ -100,13 +104,15 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme private TransactionService mockedTransactionService; @Mock private RetryingTransactionHelper mockedRetryingTransactionHelper; + @Mock + private ContentStreamer contentStreamer; /** test component */ @InjectMocks private DynamicAuthoritiesGet webScript; @Override - protected DeclarativeWebScript getWebScript() + protected AbstractWebScript getWebScript() { return webScript; } @@ -255,7 +261,6 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme .thenReturn((Serializable) Collections.emptyMap()); when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) .thenReturn((Serializable) Collections.emptyMap()); - }); // Set up parameters. @@ -281,39 +286,50 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme @Test public void missingBatchSizeParameter() throws Exception { - JSONObject json = executeJSONWebScript(emptyMap()); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize is mandatory\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + try + { + executeJSONWebScript(emptyMap()); + fail("Expected exception as parameter batchsize is mandatory."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } } @Test public void invalidBatchSizeParameter() throws Exception { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "dd"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize is invalid.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "dd"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is invalid."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } } @Test public void batchSizeShouldBeGraterThanZero() throws Exception { - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "0"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"failed\",\"message\":\"Parameter batchsize should be a number greater than 0.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "0"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is not a number greater than 0."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } } @Test @@ -389,4 +405,45 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); } + + @SuppressWarnings("unchecked") + @Test + public void recordsWithExtendedSecurityAspectAndNullWritersAndReaders() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn(null); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn(null); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } } \ No newline at end of file From 8d05147c6e511fac0d9cc73c111e2474035f2d06 Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Tue, 27 Sep 2016 12:17:04 +0300 Subject: [PATCH 2/9] RM-4907: added unit tests for csv acceptance criteria and made processNode method protected --- .../scripts/roles/DynamicAuthoritiesGet.java | 2 +- .../roles/DynamicAuthoritiesGetUnitTest.java | 887 ++++++++++-------- 2 files changed, 482 insertions(+), 407 deletions(-) diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java index 82ec4dc211..d957ccdd1b 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java @@ -464,7 +464,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM * @param nodeRef */ @SuppressWarnings({ "unchecked"}) - private void processNode(NodeRef nodeRef) + protected void processNode(NodeRef nodeRef) { // get the reader/writer data Map readers = (Map)nodeService.getProperty(nodeRef, PROP_READERS); diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index c81df1251c..9ee07f681b 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -1,420 +1,214 @@ -/* - * Copyright (C) 2005-2014 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.roles; - -import static java.util.Collections.emptyMap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.roles; + +import static java.util.Collections.emptyMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableMap; - -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; -import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.domain.patch.PatchDAO; -import org.alfresco.repo.domain.qname.QNameDAO; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.patch.PatchDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.content.ContentStreamer; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; - -/** - * DynamicAuthoritiesGet Unit Test - * - * @author Silviu Dinuta - */ -@SuppressWarnings("deprecation") -public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel -{ - /** test data */ - private static final Long ASPECT_ID = 123l; - private static final QName ASPECT = AlfMock.generateQName(); - - /** mocks */ - @Mock - private PatchDAO mockedPatchDAO; - @Mock - private NodeDAO mockedNodeDAO; - @Mock - private QNameDAO mockedQnameDAO; - @Mock - private NodeService mockedNodeService; - @Mock - private PermissionService mockedPermissionService; - @Mock - private ExtendedSecurityService mockedExtendedSecurityService; - @Mock - private TransactionService mockedTransactionService; - @Mock - private RetryingTransactionHelper mockedRetryingTransactionHelper; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * DynamicAuthoritiesGet Unit Test + * + * @author Silviu Dinuta + */ +@SuppressWarnings("deprecation") +public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel +{ + /** test data */ + private static final Long ASPECT_ID = 123l; + private static final QName ASPECT = AlfMock.generateQName(); + + /** mocks */ + @Mock + private PatchDAO mockedPatchDAO; + @Mock + private NodeDAO mockedNodeDAO; + @Mock + private QNameDAO mockedQnameDAO; + @Mock + private NodeService mockedNodeService; + @Mock + private PermissionService mockedPermissionService; + @Mock + private ExtendedSecurityService mockedExtendedSecurityService; + @Mock + private TransactionService mockedTransactionService; + @Mock + private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private ContentStreamer contentStreamer; - - /** test component */ - @InjectMocks - private DynamicAuthoritiesGet webScript; - - @Override - protected AbstractWebScript getWebScript() - { - return webScript; - } - - @Override - protected String getWebScriptTemplate() - { - return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; - } - - /** - * Before test - */ - @SuppressWarnings("unchecked") - @Before - public void before() - { - MockitoAnnotations.initMocks(this); - webScript.setNodeService(mockedNodeService); - webScript.setPermissionService(mockedPermissionService); - webScript.setExtendedSecurityService(mockedExtendedSecurityService); - // setup retrying transaction helper - Answer doInTransactionAnswer = new Answer() - { - @SuppressWarnings("rawtypes") - @Override - public Object answer(InvocationOnMock invocation) throws Throwable - { - RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; - return callback.execute(); - } - }; - - doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) - . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); - - when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); - - // max node id - when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); - - // aspect - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); - } - - /** - * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens - * @throws Exception - */ - @SuppressWarnings({ "unchecked" }) - @Test - public void noNodesWithExtendedSecurity() throws Exception - { - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(Collections.emptyList()); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - - // Check the JSON result using Jackson to allow easy equality testing. - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - /** - * Given that there are records with the extended security aspect When the action is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void recordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); - - } - - /** - * Given that there are non-records with the extended security aspect When the web script is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void nonRecordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - @Test - public void missingBatchSizeParameter() throws Exception - { - try - { - executeJSONWebScript(emptyMap()); - fail("Expected exception as parameter batchsize is mandatory."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void invalidBatchSizeParameter() throws Exception - { - try - { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "dd"); - executeJSONWebScript(parameters); - fail("Expected exception as parameter batchsize is invalid."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void batchSizeShouldBeGraterThanZero() throws Exception - { - try - { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "0"); - executeJSONWebScript(parameters); - fail("Expected exception as parameter batchsize is not a number greater than 0."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void extendedSecurityAspectNotCreated() throws Exception - { - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception - { - List ids = Stream.of(1l, 2l, 3l,4l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } + /** test component */ + @InjectMocks + private DynamicAuthoritiesGet webScript; + + @Override + protected AbstractWebScript getWebScript() + { + return webScript; + } + + @Override + protected String getWebScriptTemplate() + { + return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; + } + + /** + * Before test + */ + @SuppressWarnings("unchecked") + @Before + public void before() + { + MockitoAnnotations.initMocks(this); + webScript.setNodeService(mockedNodeService); + webScript.setPermissionService(mockedPermissionService); + webScript.setExtendedSecurityService(mockedExtendedSecurityService); + // setup retrying transaction helper + Answer doInTransactionAnswer = new Answer() + { + @SuppressWarnings("rawtypes") + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; + return callback.execute(); + } + }; + + doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) + . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); + + when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); + + // max node id + when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); + + // aspect + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); + } + + /** + * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens + * + * @throws Exception + */ + @SuppressWarnings({ "unchecked" }) + @Test + public void noNodesWithExtendedSecurity() throws Exception + { + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(Collections.emptyList()); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + + // Check the JSON result using Jackson to allow easy equality testing. + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + /** + * Given that there are records with the extended security aspect When the action is executed Then the aspect is + * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API + * + * @throws Exception + */ @SuppressWarnings("unchecked") @Test - public void recordsWithExtendedSecurityAspectAndNullWritersAndReaders() throws Exception + public void recordsWithExtendedSecurityAspect() throws Exception { List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) .thenReturn(Collections.emptyList()); ids.stream().forEach((i) -> { @@ -422,9 +216,9 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn(null); + .thenReturn((Serializable) Collections.emptyMap()); when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn(null); + .thenReturn((Serializable) Collections.emptyMap()); }); @@ -437,6 +231,51 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); + + } + + /** + * Given that there are non-records with the extended security aspect When the web script is executed Then the + * aspect is removed And the dynamic authorities permissions are cleared + * + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void nonRecordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); @@ -447,4 +286,240 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); } + + @Test + public void missingBatchSizeParameter() throws Exception + { + try + { + executeJSONWebScript(emptyMap()); + fail("Expected exception as parameter batchsize is mandatory."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void invalidBatchSizeParameter() throws Exception + { + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "dd"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is invalid."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void batchSizeShouldBeGraterThanZero() throws Exception + { + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "0"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is not a number greater than 0."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void extendedSecurityAspectNotCreated() throws Exception + { + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @SuppressWarnings("unchecked") + @Test + public void recordsWithExtendedSecurityAspectAndNullWritersAndReaders() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)).thenReturn(null); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)).thenReturn(null); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + /** + * Given I have records that require migration + * And I am interested in knowning which records are migrated + * When I run the migration tool + * Then I will be returned a CSV file containing the name and node reference of the record migrated + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void processWithCSVFile() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + String name = "name" + i; + when(mockedNodeService.getProperty(nodeRef, ContentModel.PROP_NAME)).thenReturn((Serializable) name); + }); + + ArgumentCaptor csvFileCaptor = ArgumentCaptor.forClass(File.class); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4", "export", + "true"); + executeWebScript(parameters); + + verify(contentStreamer, times(1)).streamContent(any(WebScriptRequest.class), any(WebScriptResponse.class), + csvFileCaptor.capture(), any(Long.class), any(Boolean.class), any(String.class), any(Map.class)); + + File fileForDownload = csvFileCaptor.getValue(); + assertNotNull(fileForDownload); + } + + /** + * Given that I have record that require migration + * And I'm not interested in knowing which records were migrated + * When I run the migration tool + * And I will not be returned a CSV file of details. + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void processedWithouthCSVFile() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + }); + + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4", "export", + "false"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(contentStreamer, never()).streamContent(any(WebScriptRequest.class), any(WebScriptResponse.class), + any(File.class), any(Long.class), any(Boolean.class), any(String.class), any(Map.class)); + } } \ No newline at end of file From b9bb54579e050f3294da7af251e044dfee17fe7c Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Tue, 27 Sep 2016 12:30:43 +0300 Subject: [PATCH 3/9] minor formating issue --- .../roles/DynamicAuthoritiesGetUnitTest.java | 587 +++++++++--------- 1 file changed, 296 insertions(+), 291 deletions(-) diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index 9ee07f681b..d3a3280cf0 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -1,28 +1,28 @@ -/* - * Copyright (C) 2005-2014 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.roles; - -import static java.util.Collections.emptyMap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.roles; + +import static java.util.Collections.emptyMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; @@ -111,185 +111,187 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private ContentStreamer contentStreamer; - - /** test component */ - @InjectMocks - private DynamicAuthoritiesGet webScript; - - @Override + + /** test component */ + @InjectMocks + private DynamicAuthoritiesGet webScript; + + @Override protected AbstractWebScript getWebScript() - { - return webScript; - } - - @Override - protected String getWebScriptTemplate() - { - return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; - } - - /** - * Before test - */ - @SuppressWarnings("unchecked") - @Before - public void before() - { - MockitoAnnotations.initMocks(this); - webScript.setNodeService(mockedNodeService); - webScript.setPermissionService(mockedPermissionService); - webScript.setExtendedSecurityService(mockedExtendedSecurityService); - // setup retrying transaction helper - Answer doInTransactionAnswer = new Answer() - { - @SuppressWarnings("rawtypes") - @Override - public Object answer(InvocationOnMock invocation) throws Throwable - { - RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; - return callback.execute(); - } - }; - - doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) - . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); - - when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); - - // max node id - when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); - - // aspect - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); - } - - /** - * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens - * - * @throws Exception - */ - @SuppressWarnings({ "unchecked" }) - @Test - public void noNodesWithExtendedSecurity() throws Exception - { - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(Collections.emptyList()); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - - // Check the JSON result using Jackson to allow easy equality testing. - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - /** - * Given that there are records with the extended security aspect When the action is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API - * - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void recordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); - - } - - /** - * Given that there are non-records with the extended security aspect When the web script is executed Then the - * aspect is removed And the dynamic authorities permissions are cleared - * - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void nonRecordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - @Test - public void missingBatchSizeParameter() throws Exception - { + { + return webScript; + } + + @Override + protected String getWebScriptTemplate() + { + return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; + } + + /** + * Before test + */ + @SuppressWarnings("unchecked") + @Before + public void before() + { + MockitoAnnotations.initMocks(this); + webScript.setNodeService(mockedNodeService); + webScript.setPermissionService(mockedPermissionService); + webScript.setExtendedSecurityService(mockedExtendedSecurityService); + // setup retrying transaction helper + Answer doInTransactionAnswer = new Answer() + { + @SuppressWarnings("rawtypes") + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; + return callback.execute(); + } + }; + + doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) + . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); + + when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); + + // max node id + when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); + + // aspect + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); + } + + /** + * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens + * @throws Exception + */ + @SuppressWarnings({ "unchecked" }) + @Test + public void noNodesWithExtendedSecurity() throws Exception + { + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(Collections.emptyList()); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + + // Check the JSON result using Jackson to allow easy equality testing. + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + /** + * Given that there are records with the extended security aspect When the action is executed Then the aspect is + * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void recordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); + + } + + /** + * Given that there are non-records with the extended security aspect When the web script is executed Then the aspect is + * removed And the dynamic authorities permissions are cleared + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void nonRecordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + @Test + public void missingBatchSizeParameter() throws Exception + { try { executeJSONWebScript(emptyMap()); @@ -300,15 +302,15 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void invalidBatchSizeParameter() throws Exception - { + } + + @Test + public void invalidBatchSizeParameter() throws Exception + { try { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "dd"); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "dd"); executeJSONWebScript(parameters); fail("Expected exception as parameter batchsize is invalid."); } @@ -317,15 +319,15 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void batchSizeShouldBeGraterThanZero() throws Exception - { + } + + @Test + public void batchSizeShouldBeGraterThanZero() throws Exception + { try { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "0"); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "0"); executeJSONWebScript(parameters); fail("Expected exception as parameter batchsize is not a number greater than 0."); } @@ -334,79 +336,81 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void extendedSecurityAspectNotCreated() throws Exception - { - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } + } + + @Test + public void extendedSecurityAspectNotCreated() throws Exception + { + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception + { + List ids = Stream.of(1l, 2l, 3l,4l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } @SuppressWarnings("unchecked") @Test @@ -414,7 +418,8 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme { List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(ids) .thenReturn(Collections.emptyList()); ids.stream().forEach((i) -> { From 48e6cc47de682e37cb130a84f42b20a9c7660034 Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Tue, 27 Sep 2016 12:48:31 +0300 Subject: [PATCH 4/9] formatting fix --- .../roles/DynamicAuthoritiesGetUnitTest.java | 162 +++++++++--------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index d3a3280cf0..421286bc1a 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -24,91 +24,91 @@ import static java.util.Collections.emptyMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableMap; - -import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; -import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.domain.patch.PatchDAO; -import org.alfresco.repo.domain.qname.QNameDAO; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.patch.PatchDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.content.ContentStreamer; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * DynamicAuthoritiesGet Unit Test - * - * @author Silviu Dinuta - */ -@SuppressWarnings("deprecation") -public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel -{ - /** test data */ - private static final Long ASPECT_ID = 123l; - private static final QName ASPECT = AlfMock.generateQName(); - - /** mocks */ - @Mock - private PatchDAO mockedPatchDAO; - @Mock - private NodeDAO mockedNodeDAO; - @Mock - private QNameDAO mockedQnameDAO; - @Mock - private NodeService mockedNodeService; - @Mock - private PermissionService mockedPermissionService; - @Mock - private ExtendedSecurityService mockedExtendedSecurityService; - @Mock - private TransactionService mockedTransactionService; - @Mock - private RetryingTransactionHelper mockedRetryingTransactionHelper; + +/** + * DynamicAuthoritiesGet Unit Test + * + * @author Silviu Dinuta + */ +@SuppressWarnings("deprecation") +public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel +{ + /** test data */ + private static final Long ASPECT_ID = 123l; + private static final QName ASPECT = AlfMock.generateQName(); + + /** mocks */ + @Mock + private PatchDAO mockedPatchDAO; + @Mock + private NodeDAO mockedNodeDAO; + @Mock + private QNameDAO mockedQnameDAO; + @Mock + private NodeService mockedNodeService; + @Mock + private PermissionService mockedPermissionService; + @Mock + private ExtendedSecurityService mockedExtendedSecurityService; + @Mock + private TransactionService mockedTransactionService; + @Mock + private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private ContentStreamer contentStreamer; From 31c6b1e228fba50ed3828bb124791fd95e42885a Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Thu, 29 Sep 2016 18:44:06 +0300 Subject: [PATCH 5/9] RM-4162: added extra parentNodeRef parameter, checked writers and readers individually for null and added unit tests for the changes --- .../rm-webscript-context.xml | 1 + .../roles/rm-dynamicauthorities.get.desc.xml | 7 +- .../scripts/roles/DynamicAuthoritiesGet.java | 444 ++++--- .../roles/DynamicAuthoritiesGetUnitTest.java | 1021 ++++++++++------- 4 files changed, 881 insertions(+), 592 deletions(-) diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index 4657373e41..e1deb70752 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -597,6 +597,7 @@ + diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml b/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml index 7f77ed80ab..6cf7174dff 100644 --- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml +++ b/rm-server/config/alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.desc.xml @@ -2,12 +2,13 @@ Removes dynamic authorities - URL parameter batchsize is mandatory, and represents the number of records that are processed in one transaction.
+ URL parameter batchsize is mandatory, and represents the maximum number of records that can be processed in one transaction.
URL parameter maxProcessedRecords is optional, and represents the maximum number of records that will be processed in one request.
- URL parameter export is optional, and if the it's value is true, will export the processed records into a csv file.
+ URL parameter export is optional, and if the it's value is true, will export the processed records into a csv file.
+ URL parameter parentNodeRef is optional, and represents the nodeRef of the folder that contains the records to be processed.
]]>
- /api/rm/rm-dynamicauthorities?batchsize={batchsize}&maxProcessedRecords={maxProcessedRecords?}&export={export?} + /api/rm/rm-dynamicauthorities?batchsize={batchsize}&maxProcessedRecords={maxProcessedRecords?}&export={export?}&parentNodeRef={parentNodeRef?} argument admin required diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java index d957ccdd1b..78014bbdb3 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java @@ -25,12 +25,13 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import javax.servlet.http.HttpServletResponse; import org.alfresco.model.ContentModel; @@ -43,121 +44,131 @@ import org.alfresco.repo.domain.patch.PatchDAO; import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.content.ContentStreamer; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; import org.alfresco.util.TempFileProvider; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Format; -import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * Webscript used for removing dynamic authorities from the records. - * - * @author Silviu Dinuta - * @since 2.3.0.7 - */ -@SuppressWarnings("deprecation") + +/** + * Webscript used for removing dynamic authorities from the records. + * + * @author Silviu Dinuta + * @since 2.3.0.7 + */ +@SuppressWarnings("deprecation") public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsManagementModel -{ - private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0."; - private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN"; - private static final String MESSAGE_PROCESSING_END = "Processing - END"; - private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END"; - private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN"; - private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid."; - private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory"; - private static final String SUCCESS_STATUS = "success"; - /** - * The logger - */ - private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class); - private static final String BATCH_SIZE = "batchsize"; - private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords"; +{ + private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0."; + private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN"; + private static final String MESSAGE_PROCESSING_END = "Processing - END"; + private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END"; + private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN"; + private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid."; + private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory"; + private static final String MESSAGE_NODE_REF_DOES_NOT_EXIST_TEMPLATE = "Parameter parentNodeRef = {0} does not exist."; + private static final String SUCCESS_STATUS = "success"; + /** + * The logger + */ + private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class); + private static final String BATCH_SIZE = "batchsize"; + private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords"; private static final String PARAM_EXPORT = "export"; - private static final String MODEL_STATUS = "responsestatus"; - private static final String MODEL_MESSAGE = "message"; - private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records."; - private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records."; - private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed."; - - - /** services */ - private PatchDAO patchDAO; - private NodeDAO nodeDAO; - private QNameDAO qnameDAO; - private NodeService nodeService; - private PermissionService permissionService; - private ExtendedSecurityService extendedSecurityService; - private TransactionService transactionService; + private static final String PARAM_PARENT_NODE_REF = "parentNodeRef"; + private static final String MODEL_STATUS = "responsestatus"; + private static final String MODEL_MESSAGE = "message"; + private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records."; + private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records."; + private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed."; + + /** services */ + private PatchDAO patchDAO; + private NodeDAO nodeDAO; + private QNameDAO qnameDAO; + private NodeService nodeService; + private PermissionService permissionService; + private ExtendedSecurityService extendedSecurityService; + private TransactionService transactionService; /** Content Streamer */ protected ContentStreamer contentStreamer; + private FileFolderService fileFolderService; + /** service setters */ public void setPatchDAO(PatchDAO patchDAO) { this.patchDAO = patchDAO; } - + public void setNodeDAO(NodeDAO nodeDAO) { this.nodeDAO = nodeDAO; } - + public void setQnameDAO(QNameDAO qnameDAO) - { + { this.qnameDAO = qnameDAO; } - + public void setNodeService(NodeService nodeService) - { + { this.nodeService = nodeService; - } + } public void setPermissionService(PermissionService permissionService) - { + { this.permissionService = permissionService; } public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) - { + { this.extendedSecurityService = extendedSecurityService; - } + } public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; - } + } public void setContentStreamer(ContentStreamer contentStreamer) - { + { this.contentStreamer = contentStreamer; - } + } + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } protected Map buildModel(WebScriptRequest req, WebScriptResponse res) throws IOException { Map model = new HashMap(); final Long batchSize = getBatchSizeParameter(req); - // get the max node id and the extended security aspect - Long maxNodeId = patchDAO.getMaxAdmNodeID(); - final Pair recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY); - if(recordAspectPair == null) - { - model.put(MODEL_STATUS, SUCCESS_STATUS); - model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS); - logger.info(MESSAGE_NO_RECORDS_TO_PROCESS); - return model; - } - + // get the max node id and the extended security aspect + Long maxNodeId = patchDAO.getMaxAdmNodeID(); + final Pair recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY); + if (recordAspectPair == null) + { + model.put(MODEL_STATUS, SUCCESS_STATUS); + model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS); + logger.info(MESSAGE_NO_RECORDS_TO_PROCESS); + return model; + } + Long totalNumberOfRecordsToProcess = getMaxToProccessParameter(req, batchSize); boolean attach = getExportParameter(req); @@ -168,8 +179,17 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM List processedNodes = new ArrayList(); try { - processedNodes = processNodes(batchSize, maxNodeId, recordAspectPair, totalNumberOfRecordsToProcess, out, - attach); + NodeRef parentNodeRef = getParentNodeRefParameter(req); + if (parentNodeRef != null) + { + processedNodes = processChildrenNodes(parentNodeRef, batchSize.intValue(), recordAspectPair, + totalNumberOfRecordsToProcess.intValue(), out, attach); + } + else + { + processedNodes = processNodes(batchSize, maxNodeId, recordAspectPair, totalNumberOfRecordsToProcess, + out, attach); + } } finally { @@ -213,6 +233,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM /** * Get export parameter from the request + * * @param req * @return */ @@ -241,19 +262,14 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM try { String mimetype = getContainer().getFormatRegistry().getMimeType(req.getAgent(), format); - if (mimetype == null) - { - throw new WebScriptException("Web Script format '" + format + "' is not registered"); - } + if (mimetype == null) { throw new WebScriptException( + "Web Script format '" + format + "' is not registered"); } // construct model for script / template Status status = new Status(); Cache cache = new Cache(getDescription().getRequiredCache()); Map model = buildModel(req, res); - if (model == null) - { - return; - } + if (model == null) { return; } model.put("status", status); model.put("cache", cache); @@ -346,19 +362,19 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM protected Long getMaxToProccessParameter(WebScriptRequest req, final Long batchSize) { String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS); - //default total number of records to be processed to batch size value - Long totalNumberOfRecordsToProcess = batchSize; - if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) - { - try - { - totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); - } - catch(NumberFormatException ex) - { - //do nothing here, the value will remain 0L in this case - } - } + // default total number of records to be processed to batch size value + Long totalNumberOfRecordsToProcess = batchSize; + if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) + { + try + { + totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); + } + catch (NumberFormatException ex) + { + // do nothing here, the value will remain 0L in this case + } + } return totalNumberOfRecordsToProcess; } @@ -393,7 +409,30 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM } return size; } - + + /** + * Get parentNodeRef parameter from the request + * + * @param req + * @return + */ + protected NodeRef getParentNodeRefParameter(WebScriptRequest req) + { + String parentNodeRefStr = req.getParameter(PARAM_PARENT_NODE_REF); + NodeRef parentNodeRef = null; + if (StringUtils.isNotBlank(parentNodeRefStr)) + { + parentNodeRef = new NodeRef(parentNodeRefStr); + if(!nodeService.exists(parentNodeRef)) + { + String message = MessageFormat.format(MESSAGE_NODE_REF_DOES_NOT_EXIST_TEMPLATE, parentNodeRef.toString()); + logger.info(message); + throw new WebScriptException(Status.STATUS_BAD_REQUEST, message); + } + } + return parentNodeRef; + } + /** * Process nodes all nodes or the maximum number of nodes specified by batchsize or totalNumberOfRecordsToProcess * parameters @@ -407,81 +446,146 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM protected List processNodes(final Long batchSize, Long maxNodeId, final Pair recordAspectPair, Long totalNumberOfRecordsToProcess, final BufferedWriter out, final boolean attach) { - final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; - final List processedNodes = new ArrayList(); - logger.info(MESSAGE_PROCESSING_BEGIN); - // by batch size - for (Long i = 0L; i < maxNodeId; i+=batchSize) - { - if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - final Long currentIndex = i; - - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - // get the nodes with the extended security aspect applied + final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; + final List processedNodes = new ArrayList(); + logger.info(MESSAGE_PROCESSING_BEGIN); + // by batch size + for (Long i = 0L; i < maxNodeId; i += batchSize) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + final Long currentIndex = i; + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // get the nodes with the extended security aspect applied List nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, currentIndex + batchSize); - - // process each one - for (Long nodeId : nodeIds) - { - if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); - String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); - processNode(record); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); - processedNodes.add(record); + + // process each one + for (Long nodeId : nodeIds) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); + String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); + processNode(record); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); + processedNodes.add(record); if (attach) { out.write(recordName); out.write(","); out.write(record.toString()); out.write("\n"); - } + } } - - return null; - } + + return null; + } }, false, // read only - true); // requires new - } - logger.info(MESSAGE_PROCESSING_END); + true); // requires new + } + logger.info(MESSAGE_PROCESSING_END); return processedNodes; - } - - /** - * Process each node - * - * @param nodeRef - */ - @SuppressWarnings({ "unchecked"}) - protected void processNode(NodeRef nodeRef) - { - // get the reader/writer data - Map readers = (Map)nodeService.getProperty(nodeRef, PROP_READERS); - Map writers = (Map)nodeService.getProperty(nodeRef, PROP_WRITERS); - - // remove extended security aspect - nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY); - - // remove dynamic authority permissions - permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER); - permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER); - - // if record then ... - if (nodeService.hasAspect(nodeRef, ASPECT_RECORD) && readers != null && writers != null) - { - // re-set extended security via API - extendedSecurityService.set(nodeRef, readers.keySet(), writers.keySet()); - } - } -} + } + + protected List processChildrenNodes(NodeRef parentNodeRef, final int batchSize, + final Pair recordAspectPair, final int maxRecordsToProcess, final BufferedWriter out, + final boolean attach) + { + final List processedNodes = new ArrayList(); + final List children = fileFolderService.search(parentNodeRef, "*", /*filesSearch*/true, /*folderSearch*/true, /*includeSubfolders*/true); + logger.info(MESSAGE_PROCESSING_BEGIN); + // by batch size + for (int i = 0; i < children.size(); i += batchSize) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + final int currentIndex = i; + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + List nodes = children.subList(currentIndex, Math.min(currentIndex + batchSize, children.size())); + // process each one + for (FileInfo node : nodes) + { + if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + NodeRef record = node.getNodeRef(); + if (nodeService.hasAspect(record, recordAspectPair.getSecond())) + { + String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); + processNode(record); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); + processedNodes.add(record); + if (attach) + { + out.write(recordName); + out.write(","); + out.write(record.toString()); + out.write("\n"); + } + } + } + + return null; + } + }, false, // read only + true); // requires new + } + logger.info(MESSAGE_PROCESSING_END); + return processedNodes; + } + + /** + * Process each node + * + * @param nodeRef + */ + @SuppressWarnings({ "unchecked" }) + protected void processNode(NodeRef nodeRef) + { + // get the reader/writer data + Map readers = (Map) nodeService.getProperty(nodeRef, PROP_READERS); + Map writers = (Map) nodeService.getProperty(nodeRef, PROP_WRITERS); + + // remove extended security aspect + nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY); + + // remove dynamic authority permissions + permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER); + permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER); + + // if record then ... + if (nodeService.hasAspect(nodeRef, ASPECT_RECORD)) + { + Set readersKeySet = null; + if (readers != null) + { + readersKeySet = readers.keySet(); + } + Set writersKeySet = null; + if (writers != null) + { + writersKeySet = writers.keySet(); + } + // re-set extended security via API + extendedSecurityService.set(nodeRef, readersKeySet, writersKeySet); + } + } +} diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index 421286bc1a..46d38000a0 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -1,433 +1,278 @@ -/* - * Copyright (C) 2005-2014 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.roles; - -import static java.util.Collections.emptyMap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.roles; + +import static java.util.Collections.emptyMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableMap; - -import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; -import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.domain.patch.PatchDAO; -import org.alfresco.repo.domain.qname.QNameDAO; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.patch.PatchDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.content.ContentStreamer; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * DynamicAuthoritiesGet Unit Test - * - * @author Silviu Dinuta - */ -@SuppressWarnings("deprecation") -public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel -{ - /** test data */ - private static final Long ASPECT_ID = 123l; - private static final QName ASPECT = AlfMock.generateQName(); - - /** mocks */ - @Mock - private PatchDAO mockedPatchDAO; - @Mock - private NodeDAO mockedNodeDAO; - @Mock - private QNameDAO mockedQnameDAO; - @Mock - private NodeService mockedNodeService; - @Mock - private PermissionService mockedPermissionService; - @Mock - private ExtendedSecurityService mockedExtendedSecurityService; - @Mock - private TransactionService mockedTransactionService; - @Mock - private RetryingTransactionHelper mockedRetryingTransactionHelper; + +/** + * DynamicAuthoritiesGet Unit Test + * + * @author Silviu Dinuta + */ +@SuppressWarnings("deprecation") +public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel +{ + /** test data */ + private static final Long ASPECT_ID = 123l; + private static final QName ASPECT = AlfMock.generateQName(); + + /** mocks */ + @Mock + private PatchDAO mockedPatchDAO; + @Mock + private NodeDAO mockedNodeDAO; + @Mock + private QNameDAO mockedQnameDAO; + @Mock + private NodeService mockedNodeService; + @Mock + private PermissionService mockedPermissionService; + @Mock + private ExtendedSecurityService mockedExtendedSecurityService; + @Mock + private TransactionService mockedTransactionService; + @Mock + private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private ContentStreamer contentStreamer; - - /** test component */ - @InjectMocks - private DynamicAuthoritiesGet webScript; - - @Override - protected AbstractWebScript getWebScript() - { - return webScript; - } - - @Override - protected String getWebScriptTemplate() - { - return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; - } - - /** - * Before test - */ - @SuppressWarnings("unchecked") - @Before - public void before() - { - MockitoAnnotations.initMocks(this); - webScript.setNodeService(mockedNodeService); - webScript.setPermissionService(mockedPermissionService); - webScript.setExtendedSecurityService(mockedExtendedSecurityService); - // setup retrying transaction helper - Answer doInTransactionAnswer = new Answer() - { - @SuppressWarnings("rawtypes") - @Override - public Object answer(InvocationOnMock invocation) throws Throwable - { - RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; - return callback.execute(); - } - }; - - doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) - . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); - - when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); - - // max node id - when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); - - // aspect - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); - } - - /** - * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens - * @throws Exception - */ - @SuppressWarnings({ "unchecked" }) - @Test - public void noNodesWithExtendedSecurity() throws Exception - { - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(Collections.emptyList()); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - - // Check the JSON result using Jackson to allow easy equality testing. - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - /** - * Given that there are records with the extended security aspect When the action is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void recordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); - - } - - /** - * Given that there are non-records with the extended security aspect When the web script is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void nonRecordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - @Test - public void missingBatchSizeParameter() throws Exception - { - try - { - executeJSONWebScript(emptyMap()); - fail("Expected exception as parameter batchsize is mandatory."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void invalidBatchSizeParameter() throws Exception - { - try - { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "dd"); - executeJSONWebScript(parameters); - fail("Expected exception as parameter batchsize is invalid."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void batchSizeShouldBeGraterThanZero() throws Exception - { - try - { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "0"); - executeJSONWebScript(parameters); - fail("Expected exception as parameter batchsize is not a number greater than 0."); - } - catch (WebScriptException e) - { - assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", - Status.STATUS_BAD_REQUEST, e.getStatus()); - } - } - - @Test - public void extendedSecurityAspectNotCreated() throws Exception - { - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception - { - List ids = Stream.of(1l, 2l, 3l,4l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); - - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } + @Mock + private FileFolderService mockedFileFolderService; + /** test component */ + @InjectMocks + private DynamicAuthoritiesGet webScript; + + @Override + protected AbstractWebScript getWebScript() + { + return webScript; + } + + @Override + protected String getWebScriptTemplate() + { + return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; + } + + /** + * Before test + */ + @SuppressWarnings("unchecked") + @Before + public void before() + { + MockitoAnnotations.initMocks(this); + webScript.setNodeService(mockedNodeService); + webScript.setPermissionService(mockedPermissionService); + webScript.setExtendedSecurityService(mockedExtendedSecurityService); + webScript.setFileFolderService(mockedFileFolderService); + // setup retrying transaction helper + Answer doInTransactionAnswer = new Answer() + { + @SuppressWarnings("rawtypes") + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; + return callback.execute(); + } + }; + + doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) + . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); + + when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); + + // max node id + when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); + + // aspect + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); + } + + /** + * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens + * + * @throws Exception + */ + @SuppressWarnings({ "unchecked" }) + @Test + public void noNodesWithExtendedSecurity() throws Exception + { + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(Collections.emptyList()); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + + // Check the JSON result using Jackson to allow easy equality testing. + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + /** + * Given that there are records with the extended security aspect When the action is executed Then the aspect is + * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API + * + * @throws Exception + */ @SuppressWarnings("unchecked") @Test - public void recordsWithExtendedSecurityAspectAndNullWritersAndReaders() throws Exception + public void recordsWithExtendedSecurityAspect() throws Exception { List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(ids) + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) .thenReturn(Collections.emptyList()); ids.stream().forEach((i) -> { NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)).thenReturn(null); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)).thenReturn(null); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); + + } + + /** + * Given that there are non-records with the extended security aspect When the web script is executed Then the + * aspect is removed And the dynamic authorities permissions are cleared + * + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void nonRecordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); }); @@ -450,11 +295,233 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); } + @Test + public void missingBatchSizeParameter() throws Exception + { + try + { + executeJSONWebScript(emptyMap()); + fail("Expected exception as parameter batchsize is mandatory."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void invalidBatchSizeParameter() throws Exception + { + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "dd"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is invalid."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void batchSizeShouldBeGraterThanZero() throws Exception + { + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "0"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter batchsize is not a number greater than 0."); + } + catch (WebScriptException e) + { + assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @Test + public void extendedSecurityAspectNotCreated() throws Exception + { + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + public void recordsWithExtendedSecurityAspectAndNullWritersAndReaders() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)).thenReturn(null); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)).thenReturn(null); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + ArgumentCaptor readerKeysCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor writersKeysCaptor = ArgumentCaptor.forClass(Set.class); + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), readerKeysCaptor.capture(), + writersKeysCaptor.capture()); + List allReaderKeySets = readerKeysCaptor.getAllValues(); + List allWritersKeySets = writersKeysCaptor.getAllValues(); + for (Set keySet : allReaderKeySets) + { + assertNull(keySet); + } + for (Set keySet : allWritersKeySets) + { + assertNull(keySet); + } + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + public void recordsWithExtendedSecurityAspectAndNullWriters() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)).thenReturn(null); + + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + ArgumentCaptor readerKeysCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor writersKeysCaptor = ArgumentCaptor.forClass(Set.class); + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), readerKeysCaptor.capture(), + writersKeysCaptor.capture()); + List allReaderKeySets = readerKeysCaptor.getAllValues(); + List allWritersKeySets = writersKeysCaptor.getAllValues(); + for (Set keySet : allReaderKeySets) + { + assertNotNull(keySet); + } + for (Set keySet : allWritersKeySets) + { + assertNull(keySet); + } + } + /** - * Given I have records that require migration - * And I am interested in knowning which records are migrated - * When I run the migration tool - * Then I will be returned a CSV file containing the name and node reference of the record migrated + * Given I have records that require migration And I am interested in knowning which records are migrated When I run + * the migration tool Then I will be returned a CSV file containing the name and node reference of the record + * migrated + * * @throws Exception */ @SuppressWarnings("unchecked") @@ -491,10 +558,9 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme } /** - * Given that I have record that require migration - * And I'm not interested in knowing which records were migrated - * When I run the migration tool - * And I will not be returned a CSV file of details. + * Given that I have record that require migration And I'm not interested in knowing which records were migrated + * When I run the migration tool And I will not be returned a CSV file of details. + * * @throws Exception */ @SuppressWarnings("unchecked") @@ -527,4 +593,121 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme verify(contentStreamer, never()).streamContent(any(WebScriptRequest.class), any(WebScriptResponse.class), any(File.class), any(Long.class), any(Boolean.class), any(String.class), any(Map.class)); } + + @Test + public void invalidParentNodeRefParameter() throws Exception + { + try + { + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "parentNodeRef", "invalidNodeRef"); + executeJSONWebScript(parameters); + fail("Expected exception as parameter parentNodeRef is invalid."); + } + catch (WebScriptException e) + { + assertEquals("If parameter parentNodeRef is invalid then 'Internal server error' should be returned.", + Status.STATUS_INTERNAL_SERVER_ERROR, e.getStatus()); + } + } + + @Test + public void inexistentParentNodeRefParameter() throws Exception + { + try + { + NodeRef parentNodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeService.exists(parentNodeRef)).thenReturn(false); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "parentNodeRef", + parentNodeRef.toString()); + executeJSONWebScript(parameters); + fail("Expected exception as parameter parentNodeRef does not exist."); + } + catch (WebScriptException e) + { + assertEquals("If parameter parentNodeRef is does not exist then 'Bad Reequest' should be returned.", + Status.STATUS_BAD_REQUEST, e.getStatus()); + } + } + + @SuppressWarnings("unchecked") + @Test + public void processedWithParentNodeRef() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + NodeRef parentNodeRef = AlfMock.generateNodeRef(mockedNodeService); + List children = new ArrayList(); + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.hasAspect(nodeRef, ASPECT)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + String name = "name" + i; + when(mockedNodeService.getProperty(nodeRef, ContentModel.PROP_NAME)).thenReturn((Serializable) name); + FileInfo mockedFileInfo = mock(FileInfo.class); + when(mockedFileInfo.getNodeRef()).thenReturn(nodeRef); + children.add(mockedFileInfo); + }); + when(mockedFileFolderService.search(eq(parentNodeRef), eq("*"), eq(true), eq(true), eq(true))) + .thenReturn(children); + + Map parameters = ImmutableMap.of("batchsize", "3", "maxProcessedRecords", "4", "export", + "false", "parentNodeRef", parentNodeRef.toString()); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(contentStreamer, never()).streamContent(any(WebScriptRequest.class), any(WebScriptResponse.class), + any(File.class), any(Long.class), any(Boolean.class), any(String.class), any(Map.class)); + } + + @SuppressWarnings("unchecked") + @Test + public void processedWithParentNodeRefWithFirstTwoBatchesAlreadyProcessed() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l).collect(Collectors.toList()); + NodeRef parentNodeRef = AlfMock.generateNodeRef(mockedNodeService); + List children = new ArrayList(); + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + if (i <= 6l) + { + when(mockedNodeService.hasAspect(nodeRef, ASPECT)).thenReturn(false); + } + else + { + when(mockedNodeService.hasAspect(nodeRef, ASPECT)).thenReturn(true); + } + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + String name = "name" + i; + when(mockedNodeService.getProperty(nodeRef, ContentModel.PROP_NAME)).thenReturn((Serializable) name); + FileInfo mockedFileInfo = mock(FileInfo.class); + when(mockedFileInfo.getNodeRef()).thenReturn(nodeRef); + children.add(mockedFileInfo); + }); + when(mockedFileFolderService.search(eq(parentNodeRef), eq("*"), eq(true), eq(true), eq(true))) + .thenReturn(children); + + Map parameters = ImmutableMap.of("batchsize", "3", "parentNodeRef", parentNodeRef.toString()); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 2 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(contentStreamer, never()).streamContent(any(WebScriptRequest.class), any(WebScriptResponse.class), + any(File.class), any(Long.class), any(Boolean.class), any(String.class), any(Map.class)); + } } \ No newline at end of file From 39a8273063667f60da17798e4e89f95ed620bcc6 Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Thu, 29 Sep 2016 22:44:37 +0300 Subject: [PATCH 6/9] RM-4162: fixed formatting --- .../scripts/roles/DynamicAuthoritiesGet.java | 323 ++++---- .../roles/DynamicAuthoritiesGetUnitTest.java | 743 +++++++++--------- 2 files changed, 537 insertions(+), 529 deletions(-) diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java index 78014bbdb3..7782a14534 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java @@ -25,13 +25,13 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Set; - + import javax.servlet.http.HttpServletResponse; import org.alfresco.model.ContentModel; @@ -46,64 +46,65 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti import org.alfresco.repo.web.scripts.content.ContentStreamer; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; import org.alfresco.util.TempFileProvider; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.extensions.webscripts.AbstractWebScript; -import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Format; -import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * Webscript used for removing dynamic authorities from the records. - * - * @author Silviu Dinuta - * @since 2.3.0.7 - */ -@SuppressWarnings("deprecation") + +/** + * Webscript used for removing dynamic authorities from the records. + * + * @author Silviu Dinuta + * @since 2.3.0.7 + */ +@SuppressWarnings("deprecation") public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsManagementModel -{ - private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0."; - private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN"; - private static final String MESSAGE_PROCESSING_END = "Processing - END"; - private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END"; - private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN"; - private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid."; - private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory"; +{ + private static final String MESSAGE_PARAMETER_BATCHSIZE_GREATER_THAN_ZERO = "Parameter batchsize should be a number greater than 0."; + private static final String MESSAGE_PROCESSING_BEGIN = "Processing - BEGIN"; + private static final String MESSAGE_PROCESSING_END = "Processing - END"; + private static final String MESSAGE_PROCESSING_RECORD_END_TEMPLATE = "Processing record {0} - END"; + private static final String MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE = "Processing record {0} - BEGIN"; + private static final String MESSAGE_BATCHSIZE_IS_INVALID = "Parameter batchsize is invalid."; + private static final String MESSAGE_BATCHSIZE_IS_MANDATORY = "Parameter batchsize is mandatory"; private static final String MESSAGE_NODE_REF_DOES_NOT_EXIST_TEMPLATE = "Parameter parentNodeRef = {0} does not exist."; - private static final String SUCCESS_STATUS = "success"; - /** - * The logger - */ - private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class); - private static final String BATCH_SIZE = "batchsize"; - private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords"; + private static final String SUCCESS_STATUS = "success"; + /** + * The logger + */ + private static Log logger = LogFactory.getLog(DynamicAuthoritiesGet.class); + private static final String BATCH_SIZE = "batchsize"; + private static final String TOTAL_NUMBER_TO_PROCESS = "maxProcessedRecords"; private static final String PARAM_EXPORT = "export"; private static final String PARAM_PARENT_NODE_REF = "parentNodeRef"; - private static final String MODEL_STATUS = "responsestatus"; - private static final String MODEL_MESSAGE = "message"; - private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records."; - private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records."; - private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed."; - - /** services */ - private PatchDAO patchDAO; - private NodeDAO nodeDAO; - private QNameDAO qnameDAO; - private NodeService nodeService; - private PermissionService permissionService; - private ExtendedSecurityService extendedSecurityService; - private TransactionService transactionService; + private static final String MODEL_STATUS = "responsestatus"; + private static final String MODEL_MESSAGE = "message"; + private static final String MESSAGE_ALL_TEMPLATE = "Processed {0} records."; + private static final String MESSAGE_PARTIAL_TEMPLATE = "Processed first {0} records."; + private static final String MESSAGE_NO_RECORDS_TO_PROCESS = "There where no records to be processed."; + + + /** services */ + private PatchDAO patchDAO; + private NodeDAO nodeDAO; + private QNameDAO qnameDAO; + private NodeService nodeService; + private PermissionService permissionService; + private ExtendedSecurityService extendedSecurityService; + private TransactionService transactionService; /** Content Streamer */ protected ContentStreamer contentStreamer; private FileFolderService fileFolderService; @@ -113,41 +114,41 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM { this.patchDAO = patchDAO; } - + public void setNodeDAO(NodeDAO nodeDAO) { this.nodeDAO = nodeDAO; } - + public void setQnameDAO(QNameDAO qnameDAO) - { + { this.qnameDAO = qnameDAO; } - + public void setNodeService(NodeService nodeService) - { + { this.nodeService = nodeService; - } + } public void setPermissionService(PermissionService permissionService) - { + { this.permissionService = permissionService; } public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) - { + { this.extendedSecurityService = extendedSecurityService; - } + } public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; - } + } public void setContentStreamer(ContentStreamer contentStreamer) - { + { this.contentStreamer = contentStreamer; - } + } public void setFileFolderService(FileFolderService fileFolderService) { @@ -158,17 +159,17 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM { Map model = new HashMap(); final Long batchSize = getBatchSizeParameter(req); - // get the max node id and the extended security aspect - Long maxNodeId = patchDAO.getMaxAdmNodeID(); - final Pair recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY); - if (recordAspectPair == null) - { - model.put(MODEL_STATUS, SUCCESS_STATUS); - model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS); - logger.info(MESSAGE_NO_RECORDS_TO_PROCESS); - return model; - } - + // get the max node id and the extended security aspect + Long maxNodeId = patchDAO.getMaxAdmNodeID(); + final Pair recordAspectPair = qnameDAO.getQName(ASPECT_EXTENDED_SECURITY); + if(recordAspectPair == null) + { + model.put(MODEL_STATUS, SUCCESS_STATUS); + model.put(MODEL_MESSAGE, MESSAGE_NO_RECORDS_TO_PROCESS); + logger.info(MESSAGE_NO_RECORDS_TO_PROCESS); + return model; + } + Long totalNumberOfRecordsToProcess = getMaxToProccessParameter(req, batchSize); boolean attach = getExportParameter(req); @@ -184,7 +185,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM { processedNodes = processChildrenNodes(parentNodeRef, batchSize.intValue(), recordAspectPair, totalNumberOfRecordsToProcess.intValue(), out, attach); - } + } else { processedNodes = processNodes(batchSize, maxNodeId, recordAspectPair, totalNumberOfRecordsToProcess, @@ -262,8 +263,10 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM try { String mimetype = getContainer().getFormatRegistry().getMimeType(req.getAgent(), format); - if (mimetype == null) { throw new WebScriptException( - "Web Script format '" + format + "' is not registered"); } + if (mimetype == null) + { + throw new WebScriptException("Web Script format '" + format + "' is not registered"); + } // construct model for script / template Status status = new Status(); @@ -362,19 +365,19 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM protected Long getMaxToProccessParameter(WebScriptRequest req, final Long batchSize) { String totalToBeProcessedRecordsStr = req.getParameter(TOTAL_NUMBER_TO_PROCESS); - // default total number of records to be processed to batch size value - Long totalNumberOfRecordsToProcess = batchSize; - if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) - { - try - { - totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); - } - catch (NumberFormatException ex) - { - // do nothing here, the value will remain 0L in this case - } - } + //default total number of records to be processed to batch size value + Long totalNumberOfRecordsToProcess = batchSize; + if (StringUtils.isNotBlank(totalToBeProcessedRecordsStr)) + { + try + { + totalNumberOfRecordsToProcess = Long.parseLong(totalToBeProcessedRecordsStr); + } + catch(NumberFormatException ex) + { + //do nothing here, the value will remain 0L in this case + } + } return totalNumberOfRecordsToProcess; } @@ -409,7 +412,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM } return size; } - + /** * Get parentNodeRef parameter from the request * @@ -446,57 +449,57 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM protected List processNodes(final Long batchSize, Long maxNodeId, final Pair recordAspectPair, Long totalNumberOfRecordsToProcess, final BufferedWriter out, final boolean attach) { - final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; - final List processedNodes = new ArrayList(); - logger.info(MESSAGE_PROCESSING_BEGIN); - // by batch size - for (Long i = 0L; i < maxNodeId; i += batchSize) - { - if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - final Long currentIndex = i; - - transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() - { - public Void execute() throws Throwable - { - // get the nodes with the extended security aspect applied + final Long maxRecordsToProcess = totalNumberOfRecordsToProcess; + final List processedNodes = new ArrayList(); + logger.info(MESSAGE_PROCESSING_BEGIN); + // by batch size + for (Long i = 0L; i < maxNodeId; i+=batchSize) + { + if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + final Long currentIndex = i; + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // get the nodes with the extended security aspect applied List nodeIds = patchDAO.getNodesByAspectQNameId(recordAspectPair.getFirst(), currentIndex, currentIndex + batchSize); - - // process each one - for (Long nodeId : nodeIds) - { - if (maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) - { - break; - } - NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); - String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); - processNode(record); - logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); - processedNodes.add(record); + + // process each one + for (Long nodeId : nodeIds) + { + if(maxRecordsToProcess != 0 && processedNodes.size() >= maxRecordsToProcess) + { + break; + } + NodeRef record = nodeDAO.getNodePair(nodeId).getSecond(); + String recordName = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_BEGIN_TEMPLATE, recordName)); + processNode(record); + logger.info(MessageFormat.format(MESSAGE_PROCESSING_RECORD_END_TEMPLATE, recordName)); + processedNodes.add(record); if (attach) { out.write(recordName); out.write(","); out.write(record.toString()); out.write("\n"); - } + } } - - return null; - } + + return null; + } }, false, // read only - true); // requires new - } - logger.info(MESSAGE_PROCESSING_END); + true); // requires new + } + logger.info(MESSAGE_PROCESSING_END); return processedNodes; - } - + } + protected List processChildrenNodes(NodeRef parentNodeRef, final int batchSize, final Pair recordAspectPair, final int maxRecordsToProcess, final BufferedWriter out, final boolean attach) @@ -552,31 +555,31 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM return processedNodes; } - /** - * Process each node - * - * @param nodeRef - */ - @SuppressWarnings({ "unchecked" }) - protected void processNode(NodeRef nodeRef) - { - // get the reader/writer data - Map readers = (Map) nodeService.getProperty(nodeRef, PROP_READERS); - Map writers = (Map) nodeService.getProperty(nodeRef, PROP_WRITERS); - - // remove extended security aspect - nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY); - - // remove dynamic authority permissions - permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER); - permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER); - - // if record then ... + /** + * Process each node + * + * @param nodeRef + */ + @SuppressWarnings({ "unchecked"}) + protected void processNode(NodeRef nodeRef) + { + // get the reader/writer data + Map readers = (Map)nodeService.getProperty(nodeRef, PROP_READERS); + Map writers = (Map)nodeService.getProperty(nodeRef, PROP_WRITERS); + + // remove extended security aspect + nodeService.removeAspect(nodeRef, ASPECT_EXTENDED_SECURITY); + + // remove dynamic authority permissions + permissionService.clearPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER); + permissionService.clearPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER); + + // if record then ... if (nodeService.hasAspect(nodeRef, ASPECT_RECORD)) { Set readersKeySet = null; if (readers != null) - { + { readersKeySet = readers.keySet(); } Set writersKeySet = null; @@ -584,8 +587,8 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM { writersKeySet = writers.keySet(); } - // re-set extended security via API + // re-set extended security via API extendedSecurityService.set(nodeRef, readersKeySet, writersKeySet); - } - } -} + } + } +} diff --git a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java index 46d38000a0..74baf0a4e1 100644 --- a/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGetUnitTest.java @@ -1,303 +1,307 @@ -/* - * Copyright (C) 2005-2014 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -package org.alfresco.repo.web.scripts.roles; - -import static java.util.Collections.emptyMap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +/* + * Copyright (C) 2005-2014 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.web.scripts.roles; + +import static java.util.Collections.emptyMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.io.Serializable; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.Serializable; import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableMap; - -import org.alfresco.model.ContentModel; -import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; -import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; -import org.alfresco.repo.domain.node.NodeDAO; -import org.alfresco.repo.domain.patch.PatchDAO; -import org.alfresco.repo.domain.qname.QNameDAO; -import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; +import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseWebScriptUnitTest; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.patch.PatchDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.web.scripts.content.ContentStreamer; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileInfo; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.transaction.TransactionService; -import org.alfresco.util.Pair; -import org.json.JSONObject; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.Pair; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.extensions.webscripts.AbstractWebScript; import org.springframework.extensions.webscripts.Status; -import org.springframework.extensions.webscripts.WebScriptException; -import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; import org.springframework.extensions.webscripts.WebScriptResponse; - -/** - * DynamicAuthoritiesGet Unit Test - * - * @author Silviu Dinuta - */ -@SuppressWarnings("deprecation") -public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel -{ - /** test data */ - private static final Long ASPECT_ID = 123l; - private static final QName ASPECT = AlfMock.generateQName(); - - /** mocks */ - @Mock - private PatchDAO mockedPatchDAO; - @Mock - private NodeDAO mockedNodeDAO; - @Mock - private QNameDAO mockedQnameDAO; - @Mock - private NodeService mockedNodeService; - @Mock - private PermissionService mockedPermissionService; - @Mock - private ExtendedSecurityService mockedExtendedSecurityService; - @Mock - private TransactionService mockedTransactionService; - @Mock - private RetryingTransactionHelper mockedRetryingTransactionHelper; + +/** + * DynamicAuthoritiesGet Unit Test + * + * @author Silviu Dinuta + */ +@SuppressWarnings("deprecation") +public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest implements RecordsManagementModel +{ + /** test data */ + private static final Long ASPECT_ID = 123l; + private static final QName ASPECT = AlfMock.generateQName(); + + /** mocks */ + @Mock + private PatchDAO mockedPatchDAO; + @Mock + private NodeDAO mockedNodeDAO; + @Mock + private QNameDAO mockedQnameDAO; + @Mock + private NodeService mockedNodeService; + @Mock + private PermissionService mockedPermissionService; + @Mock + private ExtendedSecurityService mockedExtendedSecurityService; + @Mock + private TransactionService mockedTransactionService; + @Mock + private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private ContentStreamer contentStreamer; @Mock private FileFolderService mockedFileFolderService; - - /** test component */ - @InjectMocks - private DynamicAuthoritiesGet webScript; - - @Override + + /** test component */ + @InjectMocks + private DynamicAuthoritiesGet webScript; + + @Override protected AbstractWebScript getWebScript() - { - return webScript; - } - - @Override - protected String getWebScriptTemplate() - { - return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; - } - - /** - * Before test - */ - @SuppressWarnings("unchecked") - @Before - public void before() - { - MockitoAnnotations.initMocks(this); - webScript.setNodeService(mockedNodeService); - webScript.setPermissionService(mockedPermissionService); - webScript.setExtendedSecurityService(mockedExtendedSecurityService); + { + return webScript; + } + + @Override + protected String getWebScriptTemplate() + { + return "alfresco/templates/webscripts/org/alfresco/repository/roles/rm-dynamicauthorities.get.json.ftl"; + } + + /** + * Before test + */ + @SuppressWarnings("unchecked") + @Before + public void before() + { + MockitoAnnotations.initMocks(this); + webScript.setNodeService(mockedNodeService); + webScript.setPermissionService(mockedPermissionService); + webScript.setExtendedSecurityService(mockedExtendedSecurityService); webScript.setFileFolderService(mockedFileFolderService); - // setup retrying transaction helper - Answer doInTransactionAnswer = new Answer() - { - @SuppressWarnings("rawtypes") - @Override - public Object answer(InvocationOnMock invocation) throws Throwable - { - RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; - return callback.execute(); - } - }; - - doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) - . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); - - when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); - - // max node id - when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); - - // aspect - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); - } - - /** - * Given that there are no nodes with the extended security aspect When the action is executed Nothing happens + // setup retrying transaction helper + Answer doInTransactionAnswer = new Answer() + { + @SuppressWarnings("rawtypes") + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + RetryingTransactionCallback callback = (RetryingTransactionCallback) invocation.getArguments()[0]; + return callback.execute(); + } + }; + + doAnswer(doInTransactionAnswer).when(mockedRetryingTransactionHelper) + . doInTransaction(any(RetryingTransactionCallback.class), anyBoolean(), anyBoolean()); + + when(mockedTransactionService.getRetryingTransactionHelper()).thenReturn(mockedRetryingTransactionHelper); + + // max node id + when(mockedPatchDAO.getMaxAdmNodeID()).thenReturn(500000L); + + // aspect + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(new Pair(ASPECT_ID, ASPECT)); + } + + /** + * Given that there are no nodes with the extended security aspect + * When the action is executed Nothing happens * - * @throws Exception - */ - @SuppressWarnings({ "unchecked" }) - @Test - public void noNodesWithExtendedSecurity() throws Exception - { - when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) - .thenReturn(Collections.emptyList()); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - - // Check the JSON result using Jackson to allow easy equality testing. - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - /** - * Given that there are records with the extended security aspect When the action is executed Then the aspect is - * removed And the dynamic authorities permissions are cleared And extended security is set via the updated API + * @throws Exception + */ + @SuppressWarnings({ "unchecked" }) + @Test + public void noNodesWithExtendedSecurity() throws Exception + { + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())) + .thenReturn(Collections.emptyList()); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + + // Check the JSON result using Jackson to allow easy equality testing. + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 0 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, never()).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, never()).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, never()).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + /** + * Given that there are records with the extended security aspect + * When the action is executed + * Then the aspect is removed + * And the dynamic authorities permissions are cleared + * And extended security is set via the updated API * - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void recordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void recordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); - - } - - /** - * Given that there are non-records with the extended security aspect When the web script is executed Then the - * aspect is removed And the dynamic authorities permissions are cleared + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(true); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, times(3)).set(any(NodeRef.class), any(Set.class), any(Set.class)); + + } + + /** + * Given that there are non-records with the extended security aspect + * When the web script is executed + * Then the aspect is removed And the dynamic authorities permissions are cleared * - * @throws Exception - */ - @SuppressWarnings("unchecked") - @Test - public void nonRecordsWithExtendedSecurityAspect() throws Exception - { - List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); - + * @throws Exception + */ + @SuppressWarnings("unchecked") + @Test + public void nonRecordsWithExtendedSecurityAspect() throws Exception + { + List ids = Stream.of(1l, 2l, 3l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); - verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); - verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); - verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), - eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); - verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); - } - - @Test - public void missingBatchSizeParameter() throws Exception - { + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 3 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + + + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_READERS)); + verify(mockedNodeService, times(3)).getProperty(any(NodeRef.class), eq(PROP_WRITERS)); + verify(mockedNodeService, times(3)).removeAspect(any(NodeRef.class), eq(ASPECT_EXTENDED_SECURITY)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedReaderDynamicAuthority.EXTENDED_READER)); + verify(mockedPermissionService, times(3)).clearPermission(any(NodeRef.class), + eq(ExtendedWriterDynamicAuthority.EXTENDED_WRITER)); + verify(mockedExtendedSecurityService, never()).set(any(NodeRef.class), any(Set.class), any(Set.class)); + } + + @Test + public void missingBatchSizeParameter() throws Exception + { try { executeJSONWebScript(emptyMap()); @@ -308,15 +312,15 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is not provided then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void invalidBatchSizeParameter() throws Exception - { + } + + @Test + public void invalidBatchSizeParameter() throws Exception + { try { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "dd"); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "dd"); executeJSONWebScript(parameters); fail("Expected exception as parameter batchsize is invalid."); } @@ -325,15 +329,15 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is invalid then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void batchSizeShouldBeGraterThanZero() throws Exception - { + } + + @Test + public void batchSizeShouldBeGraterThanZero() throws Exception + { try { - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "0"); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "0"); executeJSONWebScript(parameters); fail("Expected exception as parameter batchsize is not a number greater than 0."); } @@ -342,79 +346,77 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme assertEquals("If parameter batchsize is not a number greater than 0 then 'Bad request' should be returned.", Status.STATUS_BAD_REQUEST, e.getStatus()); } - } - - @Test - public void extendedSecurityAspectNotCreated() throws Exception - { - when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "3"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l).collect(Collectors.toList()); - + } + + @Test + public void extendedSecurityAspectNotCreated() throws Exception + { + when(mockedQnameDAO.getQName(ASPECT_EXTENDED_SECURITY)).thenReturn(null); + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "3"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"There where no records to be processed.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void processAllRecordsWhenMaxProcessedRecordsIsZero() throws Exception + { + List ids = Stream.of(1l, 2l, 3l,4l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } - - @Test - public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception - { - List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); - + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "10", "maxProcessedRecords", "0"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } + + @Test + public void whenMaxProcessedRecordsIsMissingItDefaultsToBatchSize() throws Exception + { + List ids = Stream.of(1l, 2l, 3l, 4l, 5l).collect(Collectors.toList()); + when(mockedPatchDAO.getNodesByAspectQNameId(eq(ASPECT_ID), anyLong(), anyLong())).thenReturn(ids) - .thenReturn(Collections.emptyList()); - - ids.stream().forEach((i) -> { - NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); - when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); - when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); - when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) - .thenReturn((Serializable) Collections.emptyMap()); - when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) - .thenReturn((Serializable) Collections.emptyMap()); - - }); - - // Set up parameters. - Map parameters = ImmutableMap.of("batchsize", "4"); - JSONObject json = executeJSONWebScript(parameters); - assertNotNull(json); - String actualJSONString = json.toString(); - ObjectMapper mapper = new ObjectMapper(); - String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; - assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); - } + .thenReturn(Collections.emptyList()); + + ids.stream().forEach((i) -> { + NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService); + when(mockedNodeDAO.getNodePair(i)).thenReturn(new Pair(i, nodeRef)); + when(mockedNodeService.hasAspect(nodeRef, ASPECT_RECORD)).thenReturn(false); + when(mockedNodeService.getProperty(nodeRef, PROP_READERS)) + .thenReturn((Serializable) Collections.emptyMap()); + when(mockedNodeService.getProperty(nodeRef, PROP_WRITERS)) + .thenReturn((Serializable) Collections.emptyMap()); + }); + + // Set up parameters. + Map parameters = ImmutableMap.of("batchsize", "4"); + JSONObject json = executeJSONWebScript(parameters); + assertNotNull(json); + String actualJSONString = json.toString(); + ObjectMapper mapper = new ObjectMapper(); + String expectedJSONString = "{\"responsestatus\":\"success\",\"message\":\"Processed first 4 records.\"}"; + assertEquals(mapper.readTree(expectedJSONString), mapper.readTree(actualJSONString)); + } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test @@ -518,9 +520,10 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme } /** - * Given I have records that require migration And I am interested in knowning which records are migrated When I run - * the migration tool Then I will be returned a CSV file containing the name and node reference of the record - * migrated + * Given I have records that require migration + * And I am interested in knowning which records are migrated + * When I run the migration tool + * Then I will be returned a CSV file containing the name and node reference of the record migrated * * @throws Exception */ @@ -558,8 +561,10 @@ public class DynamicAuthoritiesGetUnitTest extends BaseWebScriptUnitTest impleme } /** - * Given that I have record that require migration And I'm not interested in knowing which records were migrated - * When I run the migration tool And I will not be returned a CSV file of details. + * Given that I have record that require migration + * And I'm not interested in knowing which records were migrated + * When I run the migration tool + * Then I will not be returned a CSV file of details. * * @throws Exception */ From c336a70846826b4bd56c5f8ab19adfada89afd96 Mon Sep 17 00:00:00 2001 From: Silviu Dinuta Date: Thu, 29 Sep 2016 23:02:13 +0300 Subject: [PATCH 7/9] RM-4162: formatting fix --- .../alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java index 7782a14534..97f22265a3 100644 --- a/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java +++ b/rm-server/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java @@ -185,7 +185,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM { processedNodes = processChildrenNodes(parentNodeRef, batchSize.intValue(), recordAspectPair, totalNumberOfRecordsToProcess.intValue(), out, attach); - } + } else { processedNodes = processNodes(batchSize, maxNodeId, recordAspectPair, totalNumberOfRecordsToProcess, From 228bcbd96088c2616ab15e958bd7f7a78ccefef3 Mon Sep 17 00:00:00 2001 From: Tuna Aksoy Date: Sat, 1 Oct 2016 17:21:57 +0100 Subject: [PATCH 8/9] RM-4101 (Link to, Copy to and File to rules fail when not run in background) --- .../impl/CopyMoveLinkFileToBaseAction.java | 26 ++-- .../integration/issue/IssueTestSuite.java | 3 +- .../test/integration/issue/RM4101Test.java | 121 ++++++++++++++++++ 3 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java index 8017009e82..17eda31bb9 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java @@ -125,15 +125,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); if (recordFolder == null) { - final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords; - recordFolder = getTransactionService().getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public NodeRef execute() throws Throwable - { - // get the reference to the record folder based on the relative path - return createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords); - } - }, false, true); + recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecords); } // now we have the reference to the target folder we can do some final checks to see if the action is valid @@ -259,23 +251,29 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr * @param targetisUnfiledRecords true is the target is in unfiled records * @return */ - private NodeRef createOrResolvePath(Action action, NodeRef actionedUponNodeRef, boolean targetisUnfiledRecords) + private NodeRef createOrResolvePath(final Action action, final NodeRef actionedUponNodeRef, final boolean targetisUnfiledRecords) { // get the starting context - NodeRef context = getContext(action, actionedUponNodeRef, targetisUnfiledRecords); + final NodeRef context = getContext(action, actionedUponNodeRef, targetisUnfiledRecords); NodeRef path = context; // get the path we wish to resolve String pathParameter = (String)action.getParameterValue(PARAM_PATH); - String[] pathElementsArray = StringUtils.tokenizeToStringArray(pathParameter, "/", false, true); + final String[] pathElementsArray = StringUtils.tokenizeToStringArray(pathParameter, "/", false, true); if((pathElementsArray != null) && (pathElementsArray.length > 0)) { // get the create parameter Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_PATH); - boolean create = createValue == null ? false : createValue.booleanValue(); + final boolean create = createValue == null ? false : createValue.booleanValue(); // create or resolve the specified path - path = createOrResolvePath(action, context, actionedUponNodeRef, Arrays.asList(pathElementsArray), targetisUnfiledRecords, create, false); + path = getTransactionService().getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + return createOrResolvePath(action, context, actionedUponNodeRef, Arrays.asList(pathElementsArray), targetisUnfiledRecords, create, false); + } + }, false, true); } return path; } diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java index 61b99cc2b4..56de827b02 100755 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java @@ -46,7 +46,8 @@ import org.junit.runners.Suite.SuiteClasses; RM1814Test.class, RM978Test.class, RM1887Test.class, - RM1914Test.class + RM1914Test.class, + RM4101Test.class }) public class IssueTestSuite { diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java new file mode 100644 index 0000000000..3c302264a3 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2005-2016 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.test.integration.issue; + +import java.util.UUID; + +import org.alfresco.module.org_alfresco_module_rm.action.impl.LinkToAction; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.rule.Rule; +import org.alfresco.service.cmr.rule.RuleService; +import org.alfresco.service.cmr.rule.RuleType; + +/** + * Tests issue #4101: Link to, Copy to and File to rules fail when not run in background + * + * @author Tuna Aksoy + * @since 2.3.0.8 + */ +public class RM4101Test extends BaseRMTestCase +{ + private RuleService ruleService; + + @Override + protected void initServices() + { + super.initServices(); + + ruleService = (RuleService) applicationContext.getBean("RuleService"); + } + + @Override + protected boolean isRecordTest() + { + return true; + } + + public void testRunRuleNotInBackground() throws Exception + { + final String categoryName = "category1" + UUID.randomUUID().toString(); + final NodeRef category1 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return filePlanService.createRecordCategory(filePlan, categoryName); + } + }); + + final NodeRef folder1 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return recordFolderService.createRecordFolder(category1, "folder1WithRule" + UUID.randomUUID().toString()); + } + }); + + final String folder2Name = "folder2FolderToLinkTo" + UUID.randomUUID().toString(); + final NodeRef folder2 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return recordFolderService.createRecordFolder(category1, folder2Name); + } + }); + + doTestInTransaction(new Test() + { + @Override + public Void run() + { + Action linkToAction = actionService.createAction(LinkToAction.NAME); + linkToAction.setParameterValue(LinkToAction.PARAM_PATH, "/" + categoryName + "/" + folder2Name); + + Rule rule = new Rule(); + rule.setRuleType(RuleType.INBOUND); + rule.setTitle("LinkTo"); + rule.setAction(linkToAction); + rule.setExecuteAsynchronously(false); + ruleService.saveRule(folder1, rule); + + return null; + } + }); + + doTestInTransaction(new Test() + { + @Override + public Void run() + { + utils.createRecord(folder1, "record1" + UUID.randomUUID().toString()); + return null; + } + + @Override + public void test(Void result) throws Exception + { + assertEquals(1, nodeService.getChildAssocs(folder2).size()); + } + }); + } +} From 4cb13c00521dddbc861de9fdaaa4ca376dd3e947 Mon Sep 17 00:00:00 2001 From: Tuna Aksoy Date: Sat, 1 Oct 2016 21:56:18 +0100 Subject: [PATCH 9/9] RM-4095 (Fix failing tests after merging 2.3.0.x up to master) --- .../org_alfresco_module_rm/rm-action-context.xml | 1 + .../action/impl/DestroyAction.java | 15 +++++++++++++++ .../record/InplaceRecordPermissionTest.java | 3 +-- .../test/integration/record/RecordTestSuite.java | 4 +++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml index 7c53ee1dea..1845cdf360 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml @@ -259,6 +259,7 @@ depends-on="rmDestroyRecordsScheduledForDestructionCapability"> + ${rm.ghosting.enabled} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java index b4b01a87e2..07a3bb8cb8 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java @@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExec import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.record.InplaceRecordService; import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -55,6 +56,9 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase /** Capability service */ private CapabilityService capabilityService; + /** Inplace record service */ + private InplaceRecordService inplaceRecordService; + /** Indicates if ghosting is enabled or not */ private boolean ghostingEnabled = true; @@ -74,6 +78,14 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase this.capabilityService = capabilityService; } + /** + * @param inplaceRecordService inplace record service + */ + public void setInplaceRecordService(InplaceRecordService inplaceRecordService) + { + this.inplaceRecordService = inplaceRecordService; + } + /** * @param ghostingEnabled true if ghosting is enabled, false otherwise */ @@ -152,6 +164,9 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase { // Add the ghosted aspect getNodeService().addAspect(record, ASPECT_GHOSTED, null); + + // Hide from inplace users to give the impression of destruction + inplaceRecordService.hideRecord(record); } else { diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java index b16c1472c3..ef086d2bc8 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java @@ -500,8 +500,7 @@ public class InplaceRecordPermissionTest extends BaseRMTestCase * And it's metadata is maintained * Then the inplace users will no longer see the record */ - // FIXME: See RM-4095 - public void ztestDestroyedRecordInplacePermissions() + public void testDestroyedRecordInplacePermissions() { test() .given() diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java index a374616e98..ad664420cf 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java @@ -37,7 +37,9 @@ import org.junit.runners.Suite.SuiteClasses; HideInplaceRecordTest.class, MoveInplaceRecordTest.class, ViewRecordTest.class, - LinkRecordTest.class + LinkRecordTest.class, + CreateInplaceRecordTest.class, + InplaceRecordPermissionTest.class }) public class RecordTestSuite {